-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.RandomBackground
-- Copyright : (c) 2009 Anze Slosar
-- translation to Haskell by Adam Vogt
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : <vogt.adam@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- An action to start terminals with a random background color
--
-----------------------------------------------------------------------------
module XMonad.Actions.RandomBackground (
-- * Usage
-- $usage
randomBg',
randomBg,
RandomColor(HSV,RGB)
) where
import XMonad(X, XConf(config), XConfig(terminal), io, spawn,
MonadIO, asks)
import System.Random
import Control.Monad(liftM)
import Numeric(showHex)
-- $usage
--
-- Add to your keybindings something like:
--
-- > ,((modm .|. shiftMask, xK_Return), randomBg $ HSV 0xff 0x20
-- | RandomColor fixes constraints when generating random colors. All
-- parameters should be in the range 0 -- 0xff
data RandomColor = RGB { _colorMin :: Int
, _colorMax :: Int
} -- ^ specify the minimum and maximum lowest values for each color channel.
| HSV { _colorSaturation :: Double
, _colorValue :: Double
} -- ^ specify the saturation and value, leaving the hue random.
toHex :: [Int] -> String
toHex = ("'#"++) . (++"'") . concatMap (ensure 2 . ($ "") . showHex)
where ensure x = reverse . take x . (++repeat '0') . reverse
randPermutation :: (RandomGen g) => [a] -> g -> [a]
randPermutation xs g = swap $ zip (randoms g) xs
where
swap ((True,x):(c,y):ys) = y:swap ((c,x):ys)
swap ((False,x):ys) = x:swap ys
swap x = map snd x
-- | @randomBg'@ produces a random hex number in the form @'#xxyyzz'@
randomBg' :: (MonadIO m) => RandomColor -> m String
randomBg' (RGB l h) = io $ liftM (toHex . take 3 . randomRs (l,h)) newStdGen
randomBg' (HSV s v) = io $ do
g <- newStdGen
let x = (^(2::Int)) $ fst $ randomR (0,sqrt $ pi / 3) g
return $ toHex $ map round $ randPermutation [v,(v-s)*x + s,s] g
-- | @randomBg@ starts a terminal with the background color taken from 'randomBg''
--
-- This depends on the your 'terminal' configuration field accepting an
-- argument like @-bg '#ff0023'@
randomBg :: RandomColor -> X ()
randomBg x = do
t <- asks (terminal . config)
c <- randomBg' x
spawn $ t ++ " -bg " ++ c