From 860f80a6d3dee97c1bcd85e7911b339c30f70c67 Mon Sep 17 00:00:00 2001 From: Tomas Janousek Date: Wed, 20 Oct 2021 11:33:52 +0100 Subject: [PATCH] X.H.Focus: Adapt docs to the new activation interface Fixes: https://github.com/xmonad/xmonad-contrib/issues/396 Related: https://github.com/xmonad/xmonad-contrib/pull/192 Related: https://github.com/xmonad/xmonad-contrib/pull/128 --- XMonad/Hooks/Focus.hs | 107 +++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 59 deletions(-) diff --git a/XMonad/Hooks/Focus.hs b/XMonad/Hooks/Focus.hs index d8ee959f8a..808d1e5479 100644 --- a/XMonad/Hooks/Focus.hs +++ b/XMonad/Hooks/Focus.hs @@ -4,10 +4,13 @@ -- | -- Module: XMonad.Hooks.Focus --- Description: Provide additional information about a new window. +-- Description: Extends ManageHook EDSL to work on focused windows and current workspace. -- Copyright: sgf-dma, 2016 -- Maintainer: sgf.dma@gmail.com -- +-- Extends "XMonad.ManageHook" EDSL to work on focused windows and current +-- workspace. +-- module XMonad.Hooks.Focus ( @@ -95,8 +98,8 @@ import XMonad.Hooks.ManageHelpers (currentWs) -- -- I may use one of predefined configurations. -- --- 1. Default window activation behavior is to switch to workspace with --- activated window and switch focus to it: +-- 1. The default window activation behavior (switch to workspace with +-- activated window and switch focus to it) expressed using this module: -- -- > import XMonad -- > @@ -105,44 +108,42 @@ import XMonad.Hooks.ManageHelpers (currentWs) -- > -- > main :: IO () -- > main = do --- > let mh :: ManageHook --- > mh = activateSwitchWs --- > xcf = ewmh $ def --- > { modMask = mod4Mask --- > , logHook = activateLogHook mh <+> logHook def --- > } +-- > let ah :: ManageHook +-- > ah = activateSwitchWs +-- > xcf = setEwmhActivateHook ah +-- > . ewmh $ def{ modMask = mod4Mask } -- > xmonad xcf -- -- 2. Or i may move activated window to current workspace and switch focus to -- it: -- --- > let mh :: ManageHook --- > mh = activateOnCurrentWs +-- > let ah :: ManageHook +-- > ah = activateOnCurrentWs -- -- 3. Or move activated window to current workspace, but keep focus unchanged: -- --- > let mh :: ManageHook --- > mh = activateOnCurrentKeepFocus +-- > let ah :: ManageHook +-- > ah = activateOnCurrentKeepFocus -- -- 4. I may use regular 'ManageHook' combinators for filtering, which windows -- may activate. E.g. activate all windows, except firefox: -- --- > let mh :: ManageHook --- > mh = not <$> (className =? "Firefox" <||> className =? "Firefox-esr" <||> className =? "Iceweasel") +-- > let ah :: ManageHook +-- > ah = not <$> (className =? "Firefox" <||> className =? "Firefox-esr" <||> className =? "Iceweasel") -- > --> activateSwitchWs -- -- 5. Or even use 'FocusHook' combinators. E.g. activate all windows, unless -- xterm is focused on /current/ workspace: -- --- > let mh :: ManageHook --- > mh = manageFocus (not <$> focusedCur (className =? "XTerm") +-- > let ah :: ManageHook +-- > ah = manageFocus (not <$> focusedCur (className =? "XTerm") -- > --> liftQuery activateSwitchWs) -- -- or activate all windows, unless focused window on the workspace, -- /where activated window is/, is not a xterm: -- --- > let mh :: ManageHook --- > mh = manageFocus (not <$> focused (className =? "XTerm") +-- > let ah :: ManageHook +-- > ah = manageFocus (not <$> focused (className =? "XTerm") -- > --> liftQuery activateSwitchWs) -- -- == Defining FocusHook. @@ -197,11 +198,11 @@ import XMonad.Hooks.ManageHelpers (currentWs) -- > main = do -- > let newFh :: ManageHook -- > newFh = manageFocus newFocusHook --- > acFh :: X () --- > acFh = activateLogHook (manageFocus activateFocusHook) --- > xcf = ewmh $ def +-- > acFh :: ManageHook +-- > acFh = manageFocus activateFocusHook +-- > xcf = setEwmhActivateHook acFh +-- > . ewmh $ def -- > { manageHook = newFh <+> manageHook def --- > , logHook = acFh <+> logHook def -- > , modMask = mod4Mask -- > } -- > `additionalKeys` [((mod4Mask, xK_v), toggleLock)] @@ -214,30 +215,23 @@ import XMonad.Hooks.ManageHelpers (currentWs) -- - I need 'XMonad.Hooks.EwmhDesktops' module for enabling window -- activation. -- - 'FocusHook' in 'manageHook' will be called /only/ for new windows. --- - 'FocusHook' in 'logHook' will be called /only/ for activated windows. +-- - 'FocusHook' in 'setEwmhActivateHook' will be called /only/ for activated windows. -- -- Alternatively, i may construct a single 'FocusHook' for both new and --- activated windows and then just add it to both 'manageHook' and 'logHook': --- --- > let fh :: ManageHook --- > fh = manageFocus $ (composeOne --- > [ liftQuery activated -?> activateFocusHook --- > , Just <$> newFocusHook --- > ]) --- > xcf = ewmh $ def --- > { manageHook = fh <+> manageHook def --- > , logHook = activateLogHook fh <+> logHook def +-- activated windows and then just add it to both 'manageHook' and 'setEwmhActivateHook': +-- +-- > let fh :: Bool -> ManageHook +-- > fh activated = manageFocus $ composeOne +-- > [ pure activated -?> activateFocusHook +-- > , pure True -?> newFocusHook +-- > ] +-- > xcf = setEwmhActivateHook (fh True) +-- > . ewmh $ def +-- > { manageHook = fh False <+> manageHook def -- > , modMask = mod4Mask -- > } -- > `additionalKeys` [((mod4Mask, xK_v), toggleLock)] -- --- Note: --- - Predicate 'activated' will be 'True' for activated window. --- - The order, when constructing final 'FocusHook': 'FocusHook' without --- 'activated' predicate will match to activated windows too, thus i should --- place it after one with 'activated' (so the latter will have a chance to --- handle activated window first). --- -- And more technical notes: -- -- - 'FocusHook' will run /many/ times, so it usually should not keep state @@ -264,11 +258,6 @@ import XMonad.Hooks.ManageHelpers (currentWs) -- -- now @FH2@ will see window shift made by @FH1@. -- --- Also, note, that if several 'activateLogHook'-s are sequenced, only --- /first/ one (leftmost) will run. Thus, to make above working, --- 'mappend' all 'ManageHook'-s first, and then run by /single/ --- 'activateLogHook' (see next example). --- -- Another interesting example is moving all activated windows to current -- workspace by default, and applying 'FocusHook' after: -- @@ -281,14 +270,14 @@ import XMonad.Hooks.ManageHelpers (currentWs) -- > -- > main :: IO () -- > main = do --- > let fh :: ManageHook --- > fh = manageFocus $ (composeOne --- > [ liftQuery activated -?> (newOnCur --> keepFocus) --- > , Just <$> newFocusHook --- > ]) --- > xcf = ewmh $ def --- > { manageHook = fh <+> manageHook def --- > , logHook = activateLogHook (fh <+> activateOnCurrentWs) <+> logHook def +-- > let fh :: Bool -> ManageHook +-- > fh activated = manageFocus $ composeOne +-- > [ pure activated -?> (newOnCur --> keepFocus) +-- > , pure True -?> newFocusHook +-- > ] +-- > xcf = setEwmhActivateHook (fh True <+> activateOnCurrentWs) +-- > . ewmh $ def +-- > { manageHook = fh False <+> manageHook def -- > , modMask = mod4Mask -- > } -- > `additionalKeys` [((mod4Mask, xK_v), toggleLock)] @@ -319,11 +308,10 @@ import XMonad.Hooks.ManageHelpers (currentWs) -- -- - i keep focus, when activated window appears on current workspace, in -- this example. --- - when @liftQuery activated -?> (newOnCur --> keepFocus)@ runs, activated +-- - when @pure activated -?> (newOnCur --> keepFocus)@ runs, activated -- window will be /already/ on current workspace, thus, if i do not want to -- move some activated windows, i should filter them out before applying -- @activateOnCurrentWs@ 'FocusHook'. --- - i 'mappend' all 'ManageHook'-s and run 'activateLogHook' only once. -- FocusQuery. @@ -552,21 +540,22 @@ when' b mx -- $examples -- | Default EWMH window activation behavior: switch to workspace with --- activated window and switch focus to it. +-- activated window and switch focus to it. Not to be used in a 'manageHook'. activateSwitchWs :: ManageHook activateSwitchWs = manageFocus (switchWorkspace <+> switchFocus) --- | Move activated window to current workspace. +-- | Move activated window to current workspace. Not to be used in a 'manageHook'. activateOnCurrent' :: ManageHook activateOnCurrent' = currentWs >>= unlessFocusLock . doShift -- | Move activated window to current workspace and switch focus to it. Note, -- that i need to explicitly call 'switchFocus' here, because otherwise, when -- activated window is /already/ on current workspace, focus won't be --- switched. +-- switched. Not to be used in a 'manageHook'. activateOnCurrentWs :: ManageHook activateOnCurrentWs = manageFocus (newOnCur --> switchFocus) <+> activateOnCurrent' -- | Move activated window to current workspace, but keep focus unchanged. +-- Not to be used in a 'manageHook'. activateOnCurrentKeepFocus :: ManageHook activateOnCurrentKeepFocus = manageFocus (newOnCur --> keepFocus) <+> activateOnCurrent'