-- |
-- Module: WildBind.Task.X11
-- Description: Task to install and export everything you need to use WildBind in X11
-- Maintainer: Toshio Ito <debug.ito@gmail.com>
-- 
-- This module exports everything you probably need to use WildBind in
-- X11 environments.
module WildBind.Task.X11
       ( -- * Execution
         wildNumPad,
         wildNumPad',
         -- * Re-exports
         module WildBind.Binding,
         module WildBind.Description,
         module WildBind.Input.NumPad,
         -- ** From basic modules
         module Control.Monad.IO.Class,
         module Control.Monad.Trans.State,
         module Data.Monoid,
         Text,
         -- ** From "WindBind.X11"
         Window, ActiveWindow, winInstance, winClass, winName,
         -- ** From "WildBind.Indicator"
         Indicator, NumPadPosition(..), updateDescription, getPresence, setPresence, togglePresence, quit
       ) where

import Control.Monad.IO.Class
import Control.Monad.Trans.State
import Data.Monoid
import Data.Text (Text)

import WildBind.Binding
import WildBind.Description
import WildBind.Input.NumPad
import WildBind.X11
  ( Window, ActiveWindow, winInstance, winClass, winName,
    withFrontEnd
  )
import WildBind.Indicator
  ( Indicator, NumPadPosition(..),
    updateDescription, getPresence, setPresence, togglePresence, quit,
    withNumPadIndicator, wildBindWithIndicator, toggleBinding
  )
import WildBind.X11.Internal.Key (XKeyInput)

-- | A convenient function to create an executable action with X11
-- 'FrontEnd' and 'Indicator' for a number pad.
--
-- > main :: IO ()
-- > main = wildNumPad $ binds $ do
-- >   on NumCenter `run` putStrLn "You pushed center."
-- 
-- Note that the executable must be compiled by ghc with
-- __@-threaded@ option enabled.__
--
-- With this function, the @"/"@ (divide) key on the numpad is bound
-- to toggling the 'Indicator', ignoring the binding you provide.
--
-- For the input type @i@, you can use 'NumPadUnlocked' or
-- 'NumPadLocked'.
wildNumPad :: (NumPadPosition i, XKeyInput i, Describable i, Ord i, Enum i, Bounded i)
              => Binding ActiveWindow i -> IO ()
wildNumPad :: forall i.
(NumPadPosition i, XKeyInput i, Describable i, Ord i, Enum i,
 Bounded i) =>
Binding ActiveWindow i -> IO ()
wildNumPad Binding ActiveWindow i
orig_binding = (Indicator ActiveWindow i -> Binding ActiveWindow i) -> IO ()
forall i.
(NumPadPosition i, XKeyInput i, Describable i, Ord i, Enum i,
 Bounded i) =>
(Indicator ActiveWindow i -> Binding ActiveWindow i) -> IO ()
wildNumPad' ((Indicator ActiveWindow i -> Binding ActiveWindow i) -> IO ())
-> (Indicator ActiveWindow i -> Binding ActiveWindow i) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Indicator ActiveWindow i
ind -> Binding ActiveWindow i
orig_binding Binding ActiveWindow i
-> Binding ActiveWindow i -> Binding ActiveWindow i
forall a. Semigroup a => a -> a -> a
<> Indicator ActiveWindow i -> NumPadLocked -> Binding ActiveWindow i
forall i s bs fs.
(NumPadPosition i, Ord i, Enum i, Bounded i) =>
Indicator s i -> NumPadLocked -> Binding' bs fs i
toggleBinding Indicator ActiveWindow i
ind NumPadLocked
NumLDivide

-- | A more flexible version of 'wildNumPad'. It passes you an
-- 'Indicator', and uses the 'Binding' you return as-is.
wildNumPad' :: (NumPadPosition i, XKeyInput i, Describable i, Ord i, Enum i, Bounded i)
               => (Indicator ActiveWindow i -> Binding ActiveWindow i) -> IO ()
wildNumPad' :: forall i.
(NumPadPosition i, XKeyInput i, Describable i, Ord i, Enum i,
 Bounded i) =>
(Indicator ActiveWindow i -> Binding ActiveWindow i) -> IO ()
wildNumPad' Indicator ActiveWindow i -> Binding ActiveWindow i
createBinding =
  (FrontEnd ActiveWindow i -> IO ()) -> IO ()
forall i a.
(XKeyInput i, Describable i, Ord i) =>
(FrontEnd ActiveWindow i -> IO a) -> IO a
withFrontEnd ((FrontEnd ActiveWindow i -> IO ()) -> IO ())
-> (FrontEnd ActiveWindow i -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \FrontEnd ActiveWindow i
front -> (Indicator ActiveWindow i -> IO ()) -> IO ()
forall i s.
(NumPadPosition i, Enum i, Bounded i) =>
(Indicator s i -> IO ()) -> IO ()
withNumPadIndicator ((Indicator ActiveWindow i -> IO ()) -> IO ())
-> (Indicator ActiveWindow i -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Indicator ActiveWindow i
ind -> Indicator ActiveWindow i
-> Binding ActiveWindow i -> FrontEnd ActiveWindow i -> IO ()
forall i s.
Ord i =>
Indicator s i -> Binding s i -> FrontEnd s i -> IO ()
wildBindWithIndicator Indicator ActiveWindow i
ind (Indicator ActiveWindow i -> Binding ActiveWindow i
createBinding Indicator ActiveWindow i
ind) FrontEnd ActiveWindow i
front