Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

X.H.EwmhDesktops: Add customization for handling the _NET_CURRENT_DESKTOP requests #923

Merged
merged 2 commits into from
Jan 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading