{-# LANGUAGE DeriveDataTypeable #-} ---------------------------------------------------------------------------- -- | -- Module : XMonad.Util.PositionStore -- Copyright : (c) Jan Vornberger 2009 -- License : BSD3-style (see LICENSE) -- -- Maintainer : jan.vornberger@informatik.uni-oldenburg.de -- Stability : unstable -- Portability : not portable -- -- A utility module to store information about position and size of a window. -- See "XMonad.Layout.PositionStoreFloat" for a layout that makes use of this. -- ----------------------------------------------------------------------------- module XMonad.Util.PositionStore ( getPosStore, modifyPosStore, posStoreInsert, posStoreMove, posStoreQuery, posStoreRemove ) where import XMonad import qualified Data.Map as M import System.Posix.Env -- Store window positions relative to the upper left screen edge -- and windows sizes as well as positions as fractions of the screen size. -- This way windows can be easily relocated and scaled when switching screens. data PositionStore = PS (M.Map Window PosStoreRectangle) deriving (Read,Show,Typeable) data PosStoreRectangle = PSRectangle Double Double Double Double deriving (Read,Show,Typeable) getPosStore :: X (PositionStore) getPosStore = do posStoreEnvM <- io $ getEnv "BLUETILE_POSITION_STORE" return $ maybe (PS M.empty) read posStoreEnvM modifyPosStore :: (PositionStore -> PositionStore) -> X () modifyPosStore f = do posStore <- getPosStore io $ setEnv "BLUETILE_POSITION_STORE" (show (f posStore)) True posStoreInsert :: PositionStore -> Window -> Rectangle -> Rectangle -> PositionStore posStoreInsert (PS posStoreMap) w (Rectangle x y wh ht) (Rectangle srX srY srWh srHt) = let offsetX = x - srX offsetY = y - srY in PS $ M.insert w (PSRectangle (fromIntegral offsetX / fromIntegral srWh) (fromIntegral offsetY / fromIntegral srHt) (fromIntegral wh / fromIntegral srWh) (fromIntegral ht / fromIntegral srHt)) posStoreMap posStoreRemove :: PositionStore -> Window -> PositionStore posStoreRemove (PS posStoreMap) w = PS $ M.delete w posStoreMap posStoreQuery :: PositionStore -> Window -> Rectangle -> Maybe Rectangle posStoreQuery (PS posStoreMap) w (Rectangle srX srY srWh srHt) = do (PSRectangle x y wh ht) <- M.lookup w posStoreMap let realWh = fromIntegral srWh * wh realHt = fromIntegral srHt * ht realOffsetX = fromIntegral srWh * x realOffsetY = fromIntegral srHt * y return (Rectangle (srX + round realOffsetX) (srY + round realOffsetY) (round realWh) (round realHt)) posStoreMove :: PositionStore -> Window -> Position -> Position -> Rectangle -> Rectangle -> PositionStore posStoreMove posStore w x y oldSr newSr = case (posStoreQuery posStore w oldSr) of Nothing -> posStore -- not in store, can't move -> do nothing Just (Rectangle _ _ wh ht) -> posStoreInsert posStore w (Rectangle x y wh ht) newSr