    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Actions.ConstrainedResize
    -- Copyright   :  (c) Dougal Stanton
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  <dougal@dougalstanton.net>
    -- Stability   :  stable
    -- Portability :  unportable
    --
    -- Lets you constrain the aspect ratio of a floating
    -- window (by, say, holding shift while you resize).
    --
    -- Useful for making a nice circular XClock window.
    --
    -----------------------------------------------------------------------------

    module XMonad.Actions.ConstrainedResize (
            -- * Usage
            -- $usage
            XMonad.Actions.ConstrainedResize.mouseResizeWindow
    ) where

    import XMonad

    -- $usage
    --
    -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
    --
    -- > import qualified XMonad.Actions.ConstrainedResize as Sqr
    --
    -- Then add something like the following to your mouse bindings:
    --
    -- >     , ((modm, button3),               (\w -> focus w >> Sqr.mouseResizeWindow w False))
    -- >     , ((modm .|. shiftMask, button3), (\w -> focus w >> Sqr.mouseResizeWindow w True ))
    --
    -- The line without the shiftMask replaces the standard mouse resize
    -- function call, so it's not completely necessary but seems neater
    -- this way.
    --
    -- For detailed instructions on editing your mouse bindings, see
    -- "XMonad.Doc.Extending#Editing_mouse_bindings".

    -- | Resize (floating) window with optional aspect ratio constraints.
    mouseResizeWindow :: Window -> Bool -> X ()
    mouseResizeWindow w c = whenX (isClient w) $ withDisplay $ \d -> do
        io $ raiseWindow d w
        wa <- io $ getWindowAttributes d w
        sh <- io $ getWMNormalHints d w
        io $ warpPointer d none w 0 0 0 0 (fromIntegral (wa_width wa)) (fromIntegral (wa_height wa))
        mouseDrag (\ex ey -> do
                     let x = ex - fromIntegral (wa_x wa)
                         y = ey - fromIntegral (wa_y wa)
                         sz = if c then (max x y, max x y) else (x,y)
                     io $ resizeWindow d w `uncurry`
                        applySizeHintsContents sh sz)
                  (float w)