Skip to content

Commit

Permalink
Merge pull request xmonad#923 from m1mir/feat/setEwmhSwitchDesktopAction
Browse files Browse the repository at this point in the history
X.H.EwmhDesktops: Add customization for handling the _NET_CURRENT_DESKTOP requests
  • Loading branch information
slotThe authored Jan 25, 2025
2 parents c0a5bc5 + 619a347 commit 6df1044
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 3 deletions.
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@
`DestroyWindowEvent` messages instead, which are broadcast to layouts
since xmonad v0.17.0.

* `XMonad.Hooks.EwmhDesktops`

- 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`.

* `XMonad.Layout.IndependentScreens`

- Added `focusWorkspace` for focusing workspaces on the screen that they
belong to.

## 0.18.1 (August 20, 2024)

### Breaking Changes
Expand Down
36 changes: 34 additions & 2 deletions XMonad/Hooks/EwmhDesktops.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ module XMonad.Hooks.EwmhDesktops (
-- $customActivate
setEwmhActivateHook,

-- ** Workspace switching
-- $customWorkspaceSwitch
setEwmhSwitchDesktopHook,

-- ** Fullscreen
-- $customFullscreen
setEwmhFullscreenHooks,
Expand Down Expand Up @@ -114,6 +118,8 @@ data EwmhDesktopsConfig =
-- ^ configurable handling of window activation requests
, fullscreenHooks :: (ManageHook, ManageHook)
-- ^ configurable handling of fullscreen state requests
, switchDesktopHook :: WorkspaceId -> WindowSet -> WindowSet
-- ^ configurable action for handling _NET_CURRENT_DESKTOP
, manageDesktopViewport :: Bool
-- ^ manage @_NET_DESKTOP_VIEWPORT@?
}
Expand All @@ -124,6 +130,7 @@ instance Default EwmhDesktopsConfig where
, workspaceRename = pure pure
, activateHook = doFocus
, fullscreenHooks = (doFullFloat, doSink)
, switchDesktopHook = W.view
, manageDesktopViewport = True
}

Expand Down Expand Up @@ -245,6 +252,31 @@ setEwmhActivateHook :: ManageHook -> XConfig l -> XConfig l
setEwmhActivateHook h = XC.modifyDef $ \c -> c{ activateHook = h }


-- $customWorkspaceSwitch
-- When a client sends a @_NET_CURRENT_DESKTOP@ request to switch to a workspace,
-- the default action used to do that is the 'W.view' function.
-- This may not be the desired behaviour in all configurations.
--
-- For example if using the "XMonad.Layout.IndependentScreens" the default action
-- might move a workspace to a screen that it isn't supposed to be on.
-- This behaviour can be fixed using the following:
--
-- > import XMonad.Actions.OnScreen
-- > import XMonad.Layout.IndependentScreens
-- >
-- > main = xmonad $ ... . setEwmhSwitchDesktopHook focusWorkspace . ewmh . ... $
-- > def{
-- > ...
-- > workspaces = withScreens 2 (workspaces def)
-- > ...
-- > }

-- | Set (replace) the action which is invoked when a client sends a
-- @_NET_CURRENT_DESKTOP@ request to switch workspace.
setEwmhSwitchDesktopHook :: (WorkspaceId -> WindowSet -> WindowSet) -> XConfig l -> XConfig l
setEwmhSwitchDesktopHook action = XC.modifyDef $ \c -> c{ switchDesktopHook = action }


-- $customFullscreen
-- When a client sends a @_NET_WM_STATE@ request to add\/remove\/toggle the
-- @_NET_WM_STATE_FULLSCREEN@ state, 'ewmhFullscreen' uses a pair of hooks to
Expand Down Expand Up @@ -449,7 +481,7 @@ mkViewPorts winset = setDesktopViewport . concat . mapMaybe (viewPorts M.!?)
ewmhDesktopsEventHook' :: Event -> EwmhDesktopsConfig -> X All
ewmhDesktopsEventHook'
ClientMessageEvent{ev_window = w, ev_message_type = mt, ev_data = d}
EwmhDesktopsConfig{workspaceSort, activateHook} =
EwmhDesktopsConfig{workspaceSort, activateHook, switchDesktopHook} =
withWindowSet $ \s -> do
sort' <- workspaceSort
let ws = sort' $ W.workspaces s
Expand All @@ -462,7 +494,7 @@ ewmhDesktopsEventHook'
if | mt == a_cw ->
killWindow w
| mt == a_cd, n : _ <- d, Just ww <- ws !? fi n ->
if W.currentTag s == W.tag ww then mempty else windows $ W.view (W.tag ww)
if W.currentTag s == W.tag ww then mempty else windows $ switchDesktopHook (W.tag ww)
| mt == a_cd ->
trace $ "Bad _NET_CURRENT_DESKTOP with data=" ++ show d
| not (w `W.member` s) ->
Expand Down
8 changes: 7 additions & 1 deletion XMonad/Layout/IndependentScreens.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module XMonad.Layout.IndependentScreens (
whenCurrentOn,
countScreens,
workspacesOn,
workspaceOnScreen, focusWindow', focusScreen, nthWorkspace, withWspOnScreen,
workspaceOnScreen, focusWindow', focusScreen, focusWorkspace, nthWorkspace, withWspOnScreen,
-- * Converting between virtual and physical workspaces
-- $converting
marshall, unmarshall, unmarshallS, unmarshallW,
Expand All @@ -40,6 +40,7 @@ import XMonad
import XMonad.Hooks.StatusBar.PP
import XMonad.Prelude
import qualified XMonad.StackSet as W
import XMonad.Actions.OnScreen (viewOnScreen)

-- $usage
-- You can use this module with the following in your @xmonad.hs@:
Expand Down Expand Up @@ -163,6 +164,11 @@ focusWindow' window ws
focusScreen :: ScreenId -> WindowSet -> WindowSet
focusScreen screenId = withWspOnScreen screenId W.view

-- | Focus the given workspace on the correct Xinerama screen.
-- An example usage can be found at `XMonad.Hooks.EwmhDesktops.setEwmhSwitchDesktopHook`
focusWorkspace :: WorkspaceId -> WindowSet -> WindowSet
focusWorkspace workspaceId = viewOnScreen (unmarshallS workspaceId) workspaceId

-- | Get the nth virtual workspace
nthWorkspace :: Int -> X (Maybe VirtualWorkspace)
nthWorkspace n = (!? n) . workspaces' <$> asks config
Expand Down

0 comments on commit 6df1044

Please sign in to comment.