diff --git a/CHANGES.md b/CHANGES.md index 13e9303bb1..4fec21e149 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -246,6 +246,10 @@ `XMonad.Actions.ToggleFullFloat` for a float-restoring implementation of fullscreening. + - Added `ewmhDesktops(Maybe)ManageHook` that places windows in their + preferred workspaces. This is useful when restoring a browser session + after a restart. + * `XMonad.Hooks.StatusBar` - Added `startAllStatusBars` to start the configured status bars. diff --git a/XMonad/Hooks/EwmhDesktops.hs b/XMonad/Hooks/EwmhDesktops.hs index 3529a55e99..905237354a 100644 --- a/XMonad/Hooks/EwmhDesktops.hs +++ b/XMonad/Hooks/EwmhDesktops.hs @@ -24,6 +24,8 @@ module XMonad.Hooks.EwmhDesktops ( -- $usage ewmh, ewmhFullscreen, + ewmhDesktopsManageHook, + ewmhDesktopsMaybeManageHook, -- * Customization -- $customization @@ -481,6 +483,31 @@ ewmhDesktopsEventHook' mempty ewmhDesktopsEventHook' _ _ = mempty +-- | A 'ManageHook' that shifts windows to the workspace they want to be in. +-- Useful for restoring browser windows to where they were before restart. +-- +-- To only use this for browsers (which might be a good idea, as many apps try +-- to restore their window to their original position, but it's rarely +-- desirable outside of security updates of multi-window apps like a browser), +-- use this: +-- +-- > stringProperty "WM_WINDOW_ROLE" =? "browser" --> ewmhDesktopsManageHook +ewmhDesktopsManageHook :: ManageHook +ewmhDesktopsManageHook = maybeToDefinite ewmhDesktopsMaybeManageHook + +-- | 'ewmhDesktopsManageHook' as a 'MaybeManageHook' for use with +-- 'composeOne'. Returns 'Nothing' if the window didn't indicate any desktop +-- preference, otherwise 'Just' (even if the preferred desktop was out of +-- bounds). +ewmhDesktopsMaybeManageHook :: MaybeManageHook +ewmhDesktopsMaybeManageHook = desktop >>= traverse doShiftI + where + doShiftI :: Int -> ManageHook + doShiftI d = do + sort' <- liftX . XC.withDef $ \EwmhDesktopsConfig{workspaceSort} -> workspaceSort + ws <- liftX . gets $ map W.tag . sort' . W.workspaces . windowset + maybe idHook doShift $ ws !? d + -- | Add EWMH fullscreen functionality to the given config. ewmhFullscreen :: XConfig a -> XConfig a ewmhFullscreen c = c { startupHook = startupHook c <> fullscreenStartup diff --git a/XMonad/Hooks/ManageHelpers.hs b/XMonad/Hooks/ManageHelpers.hs index 0d2110847e..58e37dd68e 100644 --- a/XMonad/Hooks/ManageHelpers.hs +++ b/XMonad/Hooks/ManageHelpers.hs @@ -52,6 +52,7 @@ module XMonad.Hooks.ManageHelpers ( isMinimized, isDialog, pid, + desktop, transientTo, maybeToDefinite, MaybeManageHook, @@ -202,6 +203,15 @@ pid = ask >>= \w -> liftX $ getProp32s "_NET_WM_PID" w <&> \case Just [x] -> Just (fromIntegral x) _ -> Nothing +-- | This function returns 'Just' the @_NET_WM_DESKTOP@ property for a +-- particular window if set, 'Nothing' otherwise. +-- +-- See . +desktop :: Query (Maybe Int) +desktop = ask >>= \w -> liftX $ getProp32s "_NET_WM_DESKTOP" w <&> \case + Just [x] -> Just (fromIntegral x) + _ -> Nothing + -- | A predicate to check whether a window is Transient. -- It holds the result which might be the window it is transient to -- or it might be 'Nothing'.