module Rahm.Desktop.Hooks.WindowChange where import Control.Monad (when) import Control.Monad.State (gets) import Data.Default (Default (..)) import Rahm.Desktop.Common ( getCurrentScreen, getCurrentWorkspace, ) import qualified Rahm.Desktop.StackSet as W (peek) import XMonad ( ExtensionClass (..), ScreenDetail, ScreenId, StateExtension (PersistentExtension), Window, WindowSet, WorkspaceId, X, XConfig (logHook), windowset, withWindowSet, ) import XMonad.StackSet import qualified XMonad.Util.ExtensibleState as XS (get, put) type WindowStack = StackSet WorkspaceId () Window ScreenId ScreenDetail -- Type of hook. Takes the last WindowStack and the new WindowStack newtype StackChangeHook = StackChangeHook (WindowStack -> WindowStack -> X ()) instance Semigroup StackChangeHook where (StackChangeHook f1) <> (StackChangeHook f2) = StackChangeHook $ \o n -> do f1 o n n' <- gets (mapLayout (const ()) . windowset) f2 o n' instance Monoid StackChangeHook where mempty = StackChangeHook $ \_ _ -> return () newtype LastState = LastState (Maybe WindowStack) deriving (Read, Show) instance Default LastState where def = LastState def instance ExtensionClass LastState where initialValue = def extensionType = PersistentExtension -- Creates a log hook from the function provided. -- -- The first argument to the function is the old window, the second argument in -- the new window. -- -- If the first window is Nothing, this is the first time XMonad started. withStackChangeHook :: StackChangeHook -> XConfig l -> XConfig l withStackChangeHook (StackChangeHook fn) config = config { logHook = do logHook config current <- gets (mapLayout (const ()) . windowset) LastState last <- XS.get XS.put (LastState $ Just current) when (Just current /= last) $ mapM_ (`fn` current) last }