-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Util.SessionStart
-- Description :  A module for detectiong session startup.
-- Copyright   :  (c) Markus Ongyerth 2017
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  markus@ongy.net
-- Stability   :  unstable
-- Portability :  not portable
--
-- A module for detectiong session startup.  Useful to start
-- status bars, compositors and session initialization.
-- This is a more general approach than spawnOnce and allows spawnOn etc.
-----------------------------------------------------------------------------

module XMonad.Util.SessionStart
    ( doOnce
    , isSessionStart
    , setSessionStarted
    )
where

import XMonad.Prelude (when)

import XMonad
import qualified XMonad.Util.ExtensibleState as XS

-- ---------------------------------------------------------------------
-- $usage
--
-- Add 'setSessionStarted' at the end of the 'startupHook' to set the
-- flag.
--
-- To do something only when the session is started up, use
-- 'isSessionStart' to query or wrap it in 'doOnce' to only do it when
-- the flag isn't set.
-- ---------------------------------------------------------------------

newtype SessionStart = SessionStart { SessionStart -> Bool
unSessionStart :: Bool }
    deriving (ReadPrec [SessionStart]
ReadPrec SessionStart
Int -> ReadS SessionStart
ReadS [SessionStart]
(Int -> ReadS SessionStart)
-> ReadS [SessionStart]
-> ReadPrec SessionStart
-> ReadPrec [SessionStart]
-> Read SessionStart
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SessionStart]
$creadListPrec :: ReadPrec [SessionStart]
readPrec :: ReadPrec SessionStart
$creadPrec :: ReadPrec SessionStart
readList :: ReadS [SessionStart]
$creadList :: ReadS [SessionStart]
readsPrec :: Int -> ReadS SessionStart
$creadsPrec :: Int -> ReadS SessionStart
Read, Int -> SessionStart -> ShowS
[SessionStart] -> ShowS
SessionStart -> String
(Int -> SessionStart -> ShowS)
-> (SessionStart -> String)
-> ([SessionStart] -> ShowS)
-> Show SessionStart
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SessionStart] -> ShowS
$cshowList :: [SessionStart] -> ShowS
show :: SessionStart -> String
$cshow :: SessionStart -> String
showsPrec :: Int -> SessionStart -> ShowS
$cshowsPrec :: Int -> SessionStart -> ShowS
Show)

instance ExtensionClass SessionStart where
    initialValue :: SessionStart
initialValue = Bool -> SessionStart
SessionStart Bool
True
    extensionType :: SessionStart -> StateExtension
extensionType = SessionStart -> StateExtension
forall a. (Read a, Show a, ExtensionClass a) => a -> StateExtension
PersistentExtension

-- | Use this to only do a part of your hook on session start
doOnce :: X () -> X ()
doOnce :: X () -> X ()
doOnce X ()
act = do
    Bool
startup <- X Bool
isSessionStart
    Bool -> X () -> X ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
startup X ()
act

-- | Query if the current startup is the session start
isSessionStart :: X Bool
isSessionStart :: X Bool
isSessionStart = SessionStart -> Bool
unSessionStart (SessionStart -> Bool) -> X SessionStart -> X Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> X SessionStart
forall a (m :: * -> *). (ExtensionClass a, XLike m) => m a
XS.get

-- This should become a noop/be deprecated when merged into master, and
-- the flag should be set when the state file is loaded.
-- | This currently has to be added to the end of the startup hook to
-- set the flag.
setSessionStarted :: X ()
setSessionStarted :: X ()
setSessionStarted = SessionStart -> X ()
forall a (m :: * -> *). (ExtensionClass a, XLike m) => a -> m ()
XS.put (SessionStart -> X ()) -> SessionStart -> X ()
forall a b. (a -> b) -> a -> b
$ Bool -> SessionStart
SessionStart Bool
False