{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Layout.Maximize
-- Description :  Temporarily yank the focused window out of the layout to mostly fill the screen.
-- Copyright   :  (c) 2007 James Webb
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  xmonad#jwebb,sygneca,com
-- Stability   :  unstable
-- Portability :  unportable
--
-- Temporarily yanks the focused window out of the layout to mostly fill
-- the screen.
--
-----------------------------------------------------------------------------

module XMonad.Layout.Maximize (
        -- * Usage
        -- $usage
        maximize,
        maximizeWithPadding,
        maximizeRestore,
        Maximize, MaximizeRestore,
    ) where

import XMonad
import qualified XMonad.StackSet as S
import XMonad.Layout.LayoutModifier
import XMonad.Prelude ( partition )

-- $usage
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Layout.Maximize
--
-- Then edit your @layoutHook@ by adding the Maximize layout modifier:
--
-- > myLayout = maximize (Tall 1 (3/100) (1/2)) ||| Full ||| etc..)
-- > main = xmonad def { layoutHook = myLayout }
--
-- Or, if you want to control the amount of padding placed around the
-- maximized window:
--
-- > myLayout = maximizeWithPadding 10 (Tall 1 (3/100) (1/2)) ||| Full ||| etc..)
-- > main = xmonad def { layoutHook = myLayout }
--
-- For more detailed instructions on editing the layoutHook see
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial> and
-- "XMonad.Doc.Extending#Editing_the_layout_hook".
--
-- In the key-bindings, do something like:
--
-- >        , ((modm, xK_backslash), withFocused (sendMessage . maximizeRestore))
-- >        ...
--
-- For detailed instruction on editing the key binding see:
--
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.

data Maximize a = Maximize Dimension (Maybe Window) deriving ( ReadPrec [Maximize a]
ReadPrec (Maximize a)
Int -> ReadS (Maximize a)
ReadS [Maximize a]
(Int -> ReadS (Maximize a))
-> ReadS [Maximize a]
-> ReadPrec (Maximize a)
-> ReadPrec [Maximize a]
-> Read (Maximize a)
forall a. ReadPrec [Maximize a]
forall a. ReadPrec (Maximize a)
forall a. Int -> ReadS (Maximize a)
forall a. ReadS [Maximize a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: forall a. Int -> ReadS (Maximize a)
readsPrec :: Int -> ReadS (Maximize a)
$creadList :: forall a. ReadS [Maximize a]
readList :: ReadS [Maximize a]
$creadPrec :: forall a. ReadPrec (Maximize a)
readPrec :: ReadPrec (Maximize a)
$creadListPrec :: forall a. ReadPrec [Maximize a]
readListPrec :: ReadPrec [Maximize a]
Read, Int -> Maximize a -> ShowS
[Maximize a] -> ShowS
Maximize a -> String
(Int -> Maximize a -> ShowS)
-> (Maximize a -> String)
-> ([Maximize a] -> ShowS)
-> Show (Maximize a)
forall a. Int -> Maximize a -> ShowS
forall a. [Maximize a] -> ShowS
forall a. Maximize a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Int -> Maximize a -> ShowS
showsPrec :: Int -> Maximize a -> ShowS
$cshow :: forall a. Maximize a -> String
show :: Maximize a -> String
$cshowList :: forall a. [Maximize a] -> ShowS
showList :: [Maximize a] -> ShowS
Show )
maximize :: LayoutClass l Window => l Window -> ModifiedLayout Maximize l Window
maximize :: forall (l :: * -> *).
LayoutClass l Window =>
l Window -> ModifiedLayout Maximize l Window
maximize = Maximize Window -> l Window -> ModifiedLayout Maximize l Window
forall (m :: * -> *) (l :: * -> *) a.
m a -> l a -> ModifiedLayout m l a
ModifiedLayout (Maximize Window -> l Window -> ModifiedLayout Maximize l Window)
-> Maximize Window -> l Window -> ModifiedLayout Maximize l Window
forall a b. (a -> b) -> a -> b
$ Dimension -> Maybe Window -> Maximize Window
forall a. Dimension -> Maybe Window -> Maximize a
Maximize Dimension
25 Maybe Window
forall a. Maybe a
Nothing

-- | Like 'maximize', but allows you to specify the amount of padding
-- placed around the maximized window.
maximizeWithPadding :: LayoutClass l Window => Dimension -> l Window -> ModifiedLayout Maximize l Window
maximizeWithPadding :: forall (l :: * -> *).
LayoutClass l Window =>
Dimension -> l Window -> ModifiedLayout Maximize l Window
maximizeWithPadding Dimension
padding = Maximize Window -> l Window -> ModifiedLayout Maximize l Window
forall (m :: * -> *) (l :: * -> *) a.
m a -> l a -> ModifiedLayout m l a
ModifiedLayout (Maximize Window -> l Window -> ModifiedLayout Maximize l Window)
-> Maximize Window -> l Window -> ModifiedLayout Maximize l Window
forall a b. (a -> b) -> a -> b
$ Dimension -> Maybe Window -> Maximize Window
forall a. Dimension -> Maybe Window -> Maximize a
Maximize Dimension
padding Maybe Window
forall a. Maybe a
Nothing

newtype MaximizeRestore = MaximizeRestore Window deriving ( MaximizeRestore -> MaximizeRestore -> Bool
(MaximizeRestore -> MaximizeRestore -> Bool)
-> (MaximizeRestore -> MaximizeRestore -> Bool)
-> Eq MaximizeRestore
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MaximizeRestore -> MaximizeRestore -> Bool
== :: MaximizeRestore -> MaximizeRestore -> Bool
$c/= :: MaximizeRestore -> MaximizeRestore -> Bool
/= :: MaximizeRestore -> MaximizeRestore -> Bool
Eq )
instance Message MaximizeRestore
maximizeRestore :: Window -> MaximizeRestore
maximizeRestore :: Window -> MaximizeRestore
maximizeRestore = Window -> MaximizeRestore
MaximizeRestore

instance LayoutModifier Maximize Window where
    modifierDescription :: Maximize Window -> String
modifierDescription (Maximize Dimension
_ Maybe Window
_) = String
"Maximize"
    pureModifier :: Maximize Window
-> Rectangle
-> Maybe (Stack Window)
-> [(Window, Rectangle)]
-> ([(Window, Rectangle)], Maybe (Maximize Window))
pureModifier (Maximize Dimension
padding (Just Window
target)) Rectangle
rect (Just (S.Stack Window
focused [Window]
_ [Window]
_)) [(Window, Rectangle)]
wrs =
            if Window
focused Window -> Window -> Bool
forall a. Eq a => a -> a -> Bool
== Window
target
                then ([(Window, Rectangle)]
maxed [(Window, Rectangle)]
-> [(Window, Rectangle)] -> [(Window, Rectangle)]
forall a. [a] -> [a] -> [a]
++ [(Window, Rectangle)]
rest, Maybe (Maximize Window)
forall a. Maybe a
Nothing)
                else ([(Window, Rectangle)]
rest [(Window, Rectangle)]
-> [(Window, Rectangle)] -> [(Window, Rectangle)]
forall a. [a] -> [a] -> [a]
++ [(Window, Rectangle)]
maxed, Maybe (Maximize Window)
forall {a}. Maybe (Maximize a)
lay)
        where
            ([(Window, Rectangle)]
toMax, [(Window, Rectangle)]
rest) = ((Window, Rectangle) -> Bool)
-> [(Window, Rectangle)]
-> ([(Window, Rectangle)], [(Window, Rectangle)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (\(Window
w, Rectangle
_) -> Window
w Window -> Window -> Bool
forall a. Eq a => a -> a -> Bool
== Window
target) [(Window, Rectangle)]
wrs
            maxed :: [(Window, Rectangle)]
maxed = ((Window, Rectangle) -> (Window, Rectangle))
-> [(Window, Rectangle)] -> [(Window, Rectangle)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Window
w, Rectangle
_) -> (Window
w, Rectangle
maxRect)) [(Window, Rectangle)]
toMax
            maxRect :: Rectangle
maxRect = Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle (Rectangle -> Position
rect_x Rectangle
rect Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
padding)
                                (Rectangle -> Position
rect_y Rectangle
rect Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
padding)
                                (Rectangle -> Dimension
rect_width Rectangle
rect  Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
padding Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
* Dimension
2)
                                (Rectangle -> Dimension
rect_height Rectangle
rect Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
padding Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
* Dimension
2)
            lay :: Maybe (Maximize a)
lay | [(Window, Rectangle)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Window, Rectangle)]
maxed = Maximize a -> Maybe (Maximize a)
forall a. a -> Maybe a
Just (Dimension -> Maybe Window -> Maximize a
forall a. Dimension -> Maybe Window -> Maximize a
Maximize Dimension
padding Maybe Window
forall a. Maybe a
Nothing)
                | Bool
otherwise  = Maybe (Maximize a)
forall a. Maybe a
Nothing
    pureModifier Maximize Window
_ Rectangle
_ Maybe (Stack Window)
_ [(Window, Rectangle)]
wrs = ([(Window, Rectangle)]
wrs, Maybe (Maximize Window)
forall a. Maybe a
Nothing)

    pureMess :: Maximize Window -> SomeMessage -> Maybe (Maximize Window)
pureMess (Maximize Dimension
padding Maybe Window
mw) SomeMessage
m = case SomeMessage -> Maybe MaximizeRestore
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m of
        Just (MaximizeRestore Window
w) -> case Maybe Window
mw of
            Just Window
w' -> if Window
w Window -> Window -> Bool
forall a. Eq a => a -> a -> Bool
== Window
w'
                        then Maximize Window -> Maybe (Maximize Window)
forall a. a -> Maybe a
Just (Maximize Window -> Maybe (Maximize Window))
-> Maximize Window -> Maybe (Maximize Window)
forall a b. (a -> b) -> a -> b
$ Dimension -> Maybe Window -> Maximize Window
forall a. Dimension -> Maybe Window -> Maximize a
Maximize Dimension
padding Maybe Window
forall a. Maybe a
Nothing   -- restore window
                        else Maximize Window -> Maybe (Maximize Window)
forall a. a -> Maybe a
Just (Maximize Window -> Maybe (Maximize Window))
-> Maximize Window -> Maybe (Maximize Window)
forall a b. (a -> b) -> a -> b
$ Dimension -> Maybe Window -> Maximize Window
forall a. Dimension -> Maybe Window -> Maximize a
Maximize Dimension
padding (Maybe Window -> Maximize Window)
-> Maybe Window -> Maximize Window
forall a b. (a -> b) -> a -> b
$ Window -> Maybe Window
forall a. a -> Maybe a
Just Window
w  -- maximize different window
            Maybe Window
Nothing -> Maximize Window -> Maybe (Maximize Window)
forall a. a -> Maybe a
Just (Maximize Window -> Maybe (Maximize Window))
-> Maximize Window -> Maybe (Maximize Window)
forall a b. (a -> b) -> a -> b
$ Dimension -> Maybe Window -> Maximize Window
forall a. Dimension -> Maybe Window -> Maximize a
Maximize Dimension
padding (Maybe Window -> Maximize Window)
-> Maybe Window -> Maximize Window
forall a b. (a -> b) -> a -> b
$ Window -> Maybe Window
forall a. a -> Maybe a
Just Window
w        -- maximize window
        Maybe MaximizeRestore
_ -> Maybe (Maximize Window)
forall a. Maybe a
Nothing

-- vim: sw=4:et