X.H.EwmhDesktops: Add _NET_DESKTOP_VIEWPORT support

Some panels—such as polybar—require _NET_DESKTOP_VIEWPORT support in
order to know which workspace is on which monitor.  They are then able
to only show workspaces defined on the same output as the bar with just
X11 properties.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/708
This commit is contained in:
Jose Antonio Martinez Vidaurre
2022-05-02 22:29:21 -06:00
committed by Tony Zorman
parent 6c787204aa
commit 2291d3a009
2 changed files with 41 additions and 0 deletions

View File

@@ -181,6 +181,11 @@
- Added support for dynamic scratchpads in the form of
`dynamicNSPAction` and `toggleDynamicNSP`.
* `XMonad.Hooks.EwmhDesktops`
- Added support for `_NET_DESKTOP_VIEWPORT`, which is required by
some status bars.
### Other changes
* Migrated the sample build scripts from the deprecated `xmonad-testing` repo to

View File

@@ -293,6 +293,10 @@ instance ExtensionClass WindowDesktops where initialValue = WindowDesktops (M.si
newtype ActiveWindow = ActiveWindow Window deriving Eq
instance ExtensionClass ActiveWindow where initialValue = ActiveWindow (complement none)
-- | Cached @_NET_DESKTOP_VIEWPORT@
newtype MonitorTags = MonitorTags [WorkspaceId] deriving (Show,Eq)
instance ExtensionClass MonitorTags where initialValue = MonitorTags []
-- | Compare the given value against the value in the extensible state. Run the
-- action if it has changed.
whenChanged :: (Eq a, ExtensionClass a) => a -> X () -> X ()
@@ -337,6 +341,32 @@ ewmhDesktopsLogHook' EwmhDesktopsConfig{workspaceSort, workspaceRename} = withWi
let activeWindow' = fromMaybe none (W.peek s)
whenChanged (ActiveWindow activeWindow') $ setActiveWindow activeWindow'
-- Set desktop Viewport
let visibleScreens = W.current s : W.visible s
currentTags = map (W.tag . W.workspace) visibleScreens
whenChanged (MonitorTags currentTags) $ mkViewPorts s (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.!?)
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)
mkViewPort :: WindowScreen -> WindowSpace -> (WorkspaceId, [Position])
mkViewPort scr w = (W.tag w, mkPos scr)
mkVisibleViewPort :: WindowScreen -> (WorkspaceId, [Position])
mkVisibleViewPort x = mkViewPort x (W.workspace x)
mkPos :: WindowScreen -> [Position]
mkPos scr = [rect_x (rect scr), rect_y (rect scr)]
where rect = screenRect . W.screenDetail
ewmhDesktopsEventHook' :: Event -> EwmhDesktopsConfig -> X All
ewmhDesktopsEventHook'
ClientMessageEvent{ev_window = w, ev_message_type = mt, ev_data = d}
@@ -461,6 +491,12 @@ setActiveWindow w = withDisplay $ \dpy -> do
a <- getAtom "_NET_ACTIVE_WINDOW"
io $ changeProperty32 dpy r a wINDOW propModeReplace [fromIntegral w]
setDesktopViewport :: [Position] -> X ()
setDesktopViewport positions = withDisplay $ \dpy -> do
r <- asks theRoot
a <- io $ internAtom dpy "_NET_DESKTOP_VIEWPORT" True
io $ changeProperty32 dpy r a cARDINAL propModeReplace (map fi positions)
setSupported :: X ()
setSupported = withDisplay $ \dpy -> do
r <- asks theRoot