    {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Layout.CenteredMaster
    -- Description :  Place the master pane on top of other windows; in the center or top right.
    -- Copyright   :  (c) 2009 Ilya Portnov
    -- License     :  BSD-style (see xmonad/LICENSE)
    --
    -- Maintainer  :  Ilya Portnov <portnov84@rambler.ru>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Two layout modifiers. centerMaster places master window at center,
    -- on top of all other windows, which are managed by base layout.
    -- topRightMaster is similar, but places master window in top right corner
    -- instead of center.
    --
    -----------------------------------------------------------------------------

    module XMonad.Layout.CenteredMaster (
             -- * Usage
             -- $usage

             centerMaster,
             topRightMaster,
             CenteredMaster, TopRightMaster,
             ) where

    import XMonad
    import XMonad.Layout.LayoutModifier
    import qualified XMonad.StackSet as W

    import Control.Arrow (first)

    -- $usage
    -- This module defines two new layout modifiers: centerMaster and topRightMaster.
    -- centerMaster places master window at center of screen, on top of others.
    -- All other windows in background are managed by base layout.
    -- topRightMaster is like centerMaster, but places master window in top right corner instead of center.
    --
    -- Yo can use this module by adding folowing in your @xmonad.hs@:
    --
    -- > import XMonad.Layout.CenteredMaster
    --
    -- Then add layouts to your layoutHook:
    --
    -- > myLayoutHook = centerMaster Grid ||| ...

    -- | Function that decides where master window should be placed
    type Positioner = Rectangle -> Rectangle

    -- | Data type for LayoutModifier
    data CenteredMaster a = CenteredMaster deriving (ReadPrec [CenteredMaster a]
    ReadPrec (CenteredMaster a)
    Int -> ReadS (CenteredMaster a)
    ReadS [CenteredMaster a]
    (Int -> ReadS (CenteredMaster a))
    -> ReadS [CenteredMaster a]
    -> ReadPrec (CenteredMaster a)
    -> ReadPrec [CenteredMaster a]
    -> Read (CenteredMaster a)
    forall a. ReadPrec [CenteredMaster a]
    forall a. ReadPrec (CenteredMaster a)
    forall a. Int -> ReadS (CenteredMaster a)
    forall a. ReadS [CenteredMaster a]
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: forall a. Int -> ReadS (CenteredMaster a)
    readsPrec :: Int -> ReadS (CenteredMaster a)
    $creadList :: forall a. ReadS [CenteredMaster a]
    readList :: ReadS [CenteredMaster a]
    $creadPrec :: forall a. ReadPrec (CenteredMaster a)
    readPrec :: ReadPrec (CenteredMaster a)
    $creadListPrec :: forall a. ReadPrec [CenteredMaster a]
    readListPrec :: ReadPrec [CenteredMaster a]
    Read,Int -> CenteredMaster a -> ShowS
    [CenteredMaster a] -> ShowS
    CenteredMaster a -> String
    (Int -> CenteredMaster a -> ShowS)
    -> (CenteredMaster a -> String)
    -> ([CenteredMaster a] -> ShowS)
    -> Show (CenteredMaster a)
    forall a. Int -> CenteredMaster a -> ShowS
    forall a. [CenteredMaster a] -> ShowS
    forall a. CenteredMaster a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Int -> CenteredMaster a -> ShowS
    showsPrec :: Int -> CenteredMaster a -> ShowS
    $cshow :: forall a. CenteredMaster a -> String
    show :: CenteredMaster a -> String
    $cshowList :: forall a. [CenteredMaster a] -> ShowS
    showList :: [CenteredMaster a] -> ShowS
    Show)

    instance LayoutModifier CenteredMaster Window where
      modifyLayout :: forall (l :: * -> *).
    LayoutClass l Window =>
    CenteredMaster Window
    -> Workspace String (l Window) Window
    -> Rectangle
    -> X ([(Window, Rectangle)], Maybe (l Window))
    modifyLayout CenteredMaster Window
    CenteredMaster = Positioner
    -> Workspace String (l Window) Window
    -> Rectangle
    -> X ([(Window, Rectangle)], Maybe (l Window))
    forall (l :: * -> *) a.
    (LayoutClass l a, Eq a) =>
    Positioner
    -> Workspace String (l a) a
    -> Rectangle
    -> X ([(a, Rectangle)], Maybe (l a))
    applyPosition (Float -> Float -> Positioner
    center (Float
    5Float -> Float -> Float
    forall a. Fractional a => a -> a -> a
    /Float
    7) (Float
    5Float -> Float -> Float
    forall a. Fractional a => a -> a -> a
    /Float
    7))

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

    instance LayoutModifier TopRightMaster Window where
      modifyLayout :: forall (l :: * -> *).
    LayoutClass l Window =>
    TopRightMaster Window
    -> Workspace String (l Window) Window
    -> Rectangle
    -> X ([(Window, Rectangle)], Maybe (l Window))
    modifyLayout TopRightMaster Window
    TopRightMaster = Positioner
    -> Workspace String (l Window) Window
    -> Rectangle
    -> X ([(Window, Rectangle)], Maybe (l Window))
    forall (l :: * -> *) a.
    (LayoutClass l a, Eq a) =>
    Positioner
    -> Workspace String (l a) a
    -> Rectangle
    -> X ([(a, Rectangle)], Maybe (l a))
    applyPosition (Float -> Float -> Positioner
    topRight (Float
    3Float -> Float -> Float
    forall a. Fractional a => a -> a -> a
    /Float
    7) (Float
    1Float -> Float -> Float
    forall a. Fractional a => a -> a -> a
    /Float
    2))

    -- | Modifier that puts master window in center, other windows in background
    -- are managed by given layout
    centerMaster :: LayoutClass l a => l a -> ModifiedLayout CenteredMaster l a
    centerMaster :: forall (l :: * -> *) a.
    LayoutClass l a =>
    l a -> ModifiedLayout CenteredMaster l a
    centerMaster = CenteredMaster a -> l a -> ModifiedLayout CenteredMaster l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout CenteredMaster a
    forall a. CenteredMaster a
    CenteredMaster

    -- | Modifier that puts master window in top right corner, other windows in background
    -- are managed by given layout
    topRightMaster :: LayoutClass l a => l a -> ModifiedLayout TopRightMaster l a
    topRightMaster :: forall (l :: * -> *) a.
    LayoutClass l a =>
    l a -> ModifiedLayout TopRightMaster l a
    topRightMaster = TopRightMaster a -> l a -> ModifiedLayout TopRightMaster l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout TopRightMaster a
    forall a. TopRightMaster a
    TopRightMaster

    -- | Internal function, doing main job
    applyPosition :: (LayoutClass l a, Eq a) =>
                        Positioner
                     -> W.Workspace WorkspaceId (l a) a
                     -> Rectangle
                     -> X ([(a, Rectangle)], Maybe (l a))

    applyPosition :: forall (l :: * -> *) a.
    (LayoutClass l a, Eq a) =>
    Positioner
    -> Workspace String (l a) a
    -> Rectangle
    -> X ([(a, Rectangle)], Maybe (l a))
    applyPosition Positioner
    pos Workspace String (l a) a
    wksp Rectangle
    rect = do
      let stack :: Maybe (Stack a)
    stack = Workspace String (l a) a -> Maybe (Stack a)
    forall i l a. Workspace i l a -> Maybe (Stack a)
    W.stack Workspace String (l a) a
    wksp
      let ws :: [a]
    ws = Maybe (Stack a) -> [a]
    forall a. Maybe (Stack a) -> [a]
    W.integrate' Maybe (Stack a)
    stack
      case [a]
    ws of
        []               -> Workspace String (l a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    Workspace String (layout a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))
    runLayout Workspace String (l a) a
    wksp Rectangle
    rect
        (a
    firstW : [a]
    other) -> do
           let filtStack :: Maybe (Stack a)
    filtStack = Maybe (Stack a)
    stack Maybe (Stack a) -> (Stack a -> Maybe (Stack a)) -> Maybe (Stack a)
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (a -> Bool) -> Stack a -> Maybe (Stack a)
    forall a. (a -> Bool) -> Stack a -> Maybe (Stack a)
    W.filter (a
    firstW a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    /=)
           ([(a, Rectangle)], Maybe (l a))
    wrs <- Workspace String (l a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    Workspace String (layout a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))
    runLayout (Workspace String (l a) a
    wksp {W.stack = filtStack}) Rectangle
    rect
           ([(a, Rectangle)], Maybe (l a))
    -> X ([(a, Rectangle)], Maybe (l a))
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (([(a, Rectangle)], Maybe (l a))
     -> X ([(a, Rectangle)], Maybe (l a)))
    -> ([(a, Rectangle)], Maybe (l a))
    -> X ([(a, Rectangle)], Maybe (l a))
    forall a b. (a -> b) -> a -> b
    $ ([(a, Rectangle)] -> [(a, Rectangle)])
    -> ([(a, Rectangle)], Maybe (l a))
    -> ([(a, Rectangle)], Maybe (l a))
    forall b c d. (b -> c) -> (b, d) -> (c, d)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first ((a
    firstW, Positioner -> [a] -> Positioner
    forall a. Positioner -> [a] -> Positioner
    place Positioner
    pos [a]
    other Rectangle
    rect) (a, Rectangle) -> [(a, Rectangle)] -> [(a, Rectangle)]
    forall a. a -> [a] -> [a]
    :) ([(a, Rectangle)], Maybe (l a))
    wrs

    -- | Place master window (it's Rectangle is given), using the given Positioner.
    -- If second argument is empty (that is, there is only one window on workspace),
    -- place that window fullscreen.
    place :: Positioner -> [a] -> Rectangle -> Rectangle
    place :: forall a. Positioner -> [a] -> Positioner
    place Positioner
    _ [] Rectangle
    rect = Rectangle
    rect
    place Positioner
    pos [a]
    _ Rectangle
    rect = Positioner
    pos Rectangle
    rect

    -- | Function that calculates Rectangle at top right corner of given Rectangle
    topRight :: Float -> Float -> Rectangle -> Rectangle
    topRight :: Float -> Float -> Positioner
    topRight Float
    rx Float
    ry (Rectangle Position
    sx Position
    sy Dimension
    sw Dimension
    sh) = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x Position
    sy Dimension
    w Dimension
    h
      where w :: Dimension
    w = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    sw Float -> Float -> Float
    forall a. Num a => a -> a -> a
    * Float
    rx)
            h :: Dimension
    h = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    sh Float -> Float -> Float
    forall a. Num a => a -> a -> a
    * Float
    ry)
            x :: Position
    x = Position
    sx Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    swDimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    -Dimension
    w)

    -- | Function that calculates Rectangle at center of given Rectangle.
    center :: Float -> Float -> Rectangle -> Rectangle
    center :: Float -> Float -> Positioner
    center Float
    rx Float
    ry (Rectangle Position
    sx Position
    sy Dimension
    sw Dimension
    sh) = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x Position
    y Dimension
    w Dimension
    h
      where w :: Dimension
    w = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    sw Float -> Float -> Float
    forall a. Num a => a -> a -> a
    * Float
    rx)
            h :: Dimension
    h = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    sh Float -> Float -> Float
    forall a. Num a => a -> a -> a
    * Float
    ry)
            x :: Position
    x = Position
    sx Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    swDimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    -Dimension
    w) Position -> Position -> Position
    forall a. Integral a => a -> a -> a
    `div` Position
    2
            y :: Position
    y = Position
    sy Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    shDimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    -Dimension
    h) Position -> Position -> Position
    forall a. Integral a => a -> a -> a
    `div` Position
    2