From 2b114594969ce59c51ea2312ab5cc5ef2d96de1c Mon Sep 17 00:00:00 2001 From: m1mir Date: Thu, 23 Jan 2025 16:01:42 +0100 Subject: [PATCH 1/2] X.H.EwmhDesktops: Added customization for external desktop switching. Added a configuration option to change the action for handling the _NET_CURRENT_DESKTOP requests. --- CHANGES.md | 6 ++++++ XMonad/Hooks/EwmhDesktops.hs | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b0dcf3a7d..86640753f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -39,6 +39,12 @@ `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`. + ## 0.18.1 (August 20, 2024) ### Breaking Changes diff --git a/XMonad/Hooks/EwmhDesktops.hs b/XMonad/Hooks/EwmhDesktops.hs index 1d7296859..9da99d583 100644 --- a/XMonad/Hooks/EwmhDesktops.hs +++ b/XMonad/Hooks/EwmhDesktops.hs @@ -42,6 +42,10 @@ module XMonad.Hooks.EwmhDesktops ( -- $customActivate setEwmhActivateHook, + -- ** Workspace switching + -- $customWorkspaceSwitch + setEwmhSwitchDesktopHook, + -- ** Fullscreen -- $customFullscreen setEwmhFullscreenHooks, @@ -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@? } @@ -124,6 +130,7 @@ instance Default EwmhDesktopsConfig where , workspaceRename = pure pure , activateHook = doFocus , fullscreenHooks = (doFullFloat, doSink) + , switchDesktopHook = W.view , manageDesktopViewport = True } @@ -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 @@ -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 @@ -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) -> From 619a347f3fa3a4c754ce1626b2e3b0b0ff629549 Mon Sep 17 00:00:00 2001 From: m1mir Date: Fri, 24 Jan 2025 02:52:40 +0100 Subject: [PATCH 2/2] X.L.IndependentScreens: Added focusWorkspace function. --- CHANGES.md | 5 +++++ XMonad/Layout/IndependentScreens.hs | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 86640753f..6cd65e9b6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -45,6 +45,11 @@ 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 diff --git a/XMonad/Layout/IndependentScreens.hs b/XMonad/Layout/IndependentScreens.hs index 49f110197..a84f604cf 100644 --- a/XMonad/Layout/IndependentScreens.hs +++ b/XMonad/Layout/IndependentScreens.hs @@ -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, @@ -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@: @@ -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