    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Actions.FlexibleResize
    -- Description :  Resize floating windows from any corner.
    -- Copyright   :  (c) Lukas Mai
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  <l.mai@web.de>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Resize floating windows from any corner.
    --
    -----------------------------------------------------------------------------

    module XMonad.Actions.FlexibleResize (
            -- * Usage
            -- $usage
            XMonad.Actions.FlexibleResize.mouseResizeWindow,
            XMonad.Actions.FlexibleResize.mouseResizeEdgeWindow
    ) where

    import XMonad
    import XMonad.Prelude (fi)
    import Foreign.C.Types

    -- $usage
    -- To use, first import this module into your @xmonad.hs@ file:
    --
    -- > import qualified XMonad.Actions.FlexibleResize as Flex
    --
    -- Then add an appropriate mouse binding:
    --
    -- >     , ((modm, button3), (\w -> focus w >> Flex.mouseResizeWindow w))
    --
    -- For detailed instructions on editing your mouse bindings, see
    -- "XMonad.Doc.Extending#Editing_mouse_bindings".

    -- | Resize a floating window from whichever corner the mouse is
    --   closest to.
    mouseResizeWindow
      :: Window -- ^ The window to resize.
      -> X ()
    mouseResizeWindow :: Window -> X ()
    mouseResizeWindow = Rational -> Window -> X ()
    mouseResizeEdgeWindow Rational
    0

    -- | Resize a floating window from whichever corner or edge the mouse is
    --   closest to.
    mouseResizeEdgeWindow
      :: Rational -- ^ The size of the area where only one edge is resized.
      -> Window   -- ^ The window to resize.
      -> X ()
    mouseResizeEdgeWindow :: Rational -> Window -> X ()
    mouseResizeEdgeWindow Rational
    edge Window
    w = X Bool -> X () -> X ()
    whenX (Window -> X Bool
    isClient Window
    w) (X () -> X ()) -> X () -> X ()
    forall a b. (a -> b) -> a -> b
    $ (Display -> X ()) -> X ()
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X ()) -> X ()) -> (Display -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \Display
    d ->
      Display -> Window -> (WindowAttributes -> X ()) -> X ()
    withWindowAttributes Display
    d Window
    w ((WindowAttributes -> X ()) -> X ())
    -> (WindowAttributes -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \WindowAttributes
    wa -> do
        SizeHints
    sh <- IO SizeHints -> X SizeHints
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (IO SizeHints -> X SizeHints) -> IO SizeHints -> X SizeHints
    forall a b. (a -> b) -> a -> b
    $ Display -> Window -> IO SizeHints
    getWMNormalHints Display
    d Window
    w
        (Bool
    _, Window
    _, Window
    _, CInt
    _, CInt
    _, CInt
    ix, CInt
    iy, Modifier
    _) <- IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
     -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier))
    -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    -> X (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    forall a b. (a -> b) -> a -> b
    $ Display
    -> Window
    -> IO (Bool, Window, Window, CInt, CInt, CInt, CInt, Modifier)
    queryPointer Display
    d Window
    w
        let
            pos_x :: Position
    pos_x  = CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Position) -> CInt -> Position
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_x WindowAttributes
    wa
            pos_y :: Position
    pos_y  = CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Position) -> CInt -> Position
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_y WindowAttributes
    wa
            width :: Position
    width  = CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Position) -> CInt -> Position
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_width WindowAttributes
    wa
            height :: Position
    height = CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi (CInt -> Position) -> CInt -> Position
    forall a b. (a -> b) -> a -> b
    $ WindowAttributes -> CInt
    wa_height WindowAttributes
    wa
            west :: Maybe Bool
    west  = CInt -> Position -> Maybe Bool
    findPos CInt
    ix Position
    width
            north :: Maybe Bool
    north = CInt -> Position -> Maybe Bool
    findPos CInt
    iy Position
    height
            (Position
    cx, Dimension -> Position
    fx, Position -> Dimension
    gx) = Maybe Bool
    -> Position
    -> Position
    -> (Position, Dimension -> Position, Position -> Dimension)
    mkSel Maybe Bool
    west  Position
    width  Position
    pos_x
            (Position
    cy, Dimension -> Position
    fy, Position -> Dimension
    gy) = Maybe Bool
    -> Position
    -> Position
    -> (Position, Dimension -> Position, Position -> Dimension)
    mkSel Maybe Bool
    north Position
    height Position
    pos_y
        IO () -> X ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (IO () -> X ()) -> IO () -> X ()
    forall a b. (a -> b) -> a -> b
    $ Display
    -> Window
    -> Window
    -> Position
    -> Position
    -> Dimension
    -> Dimension
    -> Position
    -> Position
    -> IO ()
    warpPointer Display
    d Window
    none Window
    w Position
    0 Position
    0 Dimension
    0 Dimension
    0 Position
    cx Position
    cy
        (Position -> Position -> X ()) -> X () -> X ()
    mouseDrag (\Position
    ex Position
    ey -> do let (Dimension
    nw,Dimension
    nh) = SizeHints -> (Dimension, Dimension) -> (Dimension, Dimension)
    forall a.
    Integral a =>
    SizeHints -> (a, a) -> (Dimension, Dimension)
    applySizeHintsContents SizeHints
    sh (Position -> Dimension
    gx Position
    ex, Position -> Dimension
    gy Position
    ey)
                                IO () -> X ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (IO () -> X ()) -> IO () -> X ()
    forall a b. (a -> b) -> a -> b
    $ Display
    -> Window
    -> Position
    -> Position
    -> Dimension
    -> Dimension
    -> IO ()
    moveResizeWindow Display
    d Window
    w (Dimension -> Position
    fx Dimension
    nw) (Dimension -> Position
    fy Dimension
    nh) Dimension
    nw Dimension
    nh
                                Window -> X ()
    float Window
    w)
                  (Window -> X ()
    float Window
    w)
        where
        findPos :: CInt -> Position -> Maybe Bool
        findPos :: CInt -> Position -> Maybe Bool
    findPos CInt
    m Position
    s
          | Rational
    p Rational -> Rational -> Bool
    forall a. Ord a => a -> a -> Bool
    < Rational
    0.5 Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    - Rational
    edgeRational -> Rational -> Rational
    forall a. Fractional a => a -> a -> a
    /Rational
    2 = Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    True
          | Rational
    p Rational -> Rational -> Bool
    forall a. Ord a => a -> a -> Bool
    < Rational
    0.5 Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    + Rational
    edgeRational -> Rational -> Rational
    forall a. Fractional a => a -> a -> a
    /Rational
    2 = Maybe Bool
    forall a. Maybe a
    Nothing
          | Bool
    otherwise = Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    False
          where
              p :: Rational
    p = CInt -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    m Rational -> Rational -> Rational
    forall a. Fractional a => a -> a -> a
    / Position -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fi Position
    s
        mkSel :: Maybe Bool -> Position -> Position -> (Position, Dimension -> Position, Position -> Dimension)
        mkSel :: Maybe Bool
    -> Position
    -> Position
    -> (Position, Dimension -> Position, Position -> Dimension)
    mkSel Maybe Bool
    b Position
    k Position
    p = case Maybe Bool
    b of
                          Just Bool
    True ->  (Position
    0, (Position -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Position
    k Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Position -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Position
    p Position -> Position -> Position
    forall a. Num a => a -> a -> a
    -)(Position -> Position)
    -> (Dimension -> Position) -> Dimension -> Position
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi, (Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Position
    k Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    + Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Position
    p Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    -)(Dimension -> Dimension)
    -> (Position -> Dimension) -> Position -> Dimension
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi)
                          Maybe Bool
    Nothing ->    (Position
    k Position -> Position -> Position
    forall a. Integral a => a -> a -> a
    `div` Position
    2, Position -> Dimension -> Position
    forall a b. a -> b -> a
    const Position
    p, Dimension -> Position -> Dimension
    forall a b. a -> b -> a
    const (Dimension -> Position -> Dimension)
    -> Dimension -> Position -> Dimension
    forall a b. (a -> b) -> a -> b
    $ Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Position
    k)
                          Just Bool
    False -> (Position
    k, Position -> Dimension -> Position
    forall a b. a -> b -> a
    const Position
    p, Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    subtract (Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Position
    p) (Dimension -> Dimension)
    -> (Position -> Dimension) -> Position -> Dimension
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi)