----------------------------------------------------------------------------- -- | -- Module : XMonad.Actions.FloatKeys -- Copyright : (c) Karsten Schoelzel <kuser@gmx.de> -- License : BSD -- -- Maintainer : Karsten Schoelzel <kuser@gmx.de> -- Stability : stable -- Portability : unportable -- -- Move and resize floating windows. ----------------------------------------------------------------------------- module XMonad.Actions.FloatKeys ( -- * Usage -- $usage keysMoveWindow, keysMoveWindowTo, keysResizeWindow, keysAbsResizeWindow, P, G, ) where import XMonad -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Actions.FloatKeys -- -- Then add appropriate key bindings, for example: -- -- > , ((modm, xK_d ), withFocused (keysResizeWindow (-10,-10) (1,1))) -- > , ((modm, xK_s ), withFocused (keysResizeWindow (10,10) (1,1))) -- > , ((modm .|. shiftMask, xK_d ), withFocused (keysAbsResizeWindow (-10,-10) (1024,752))) -- > , ((modm .|. shiftMask, xK_s ), withFocused (keysAbsResizeWindow (10,10) (1024,752))) -- > , ((modm, xK_a ), withFocused (keysMoveWindowTo (512,384) (1%2,1%2))) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". -- | @keysMoveWindow (dx, dy)@ moves the window by @dx@ pixels to the -- right and @dy@ pixels down. keysMoveWindow :: D -> Window -> X () keysMoveWindow (dx,dy) w = whenX (isClient w) $ withDisplay $ \d -> do io $ raiseWindow d w wa <- io $ getWindowAttributes d w io $ moveWindow d w (fromIntegral (fromIntegral (wa_x wa) + dx)) (fromIntegral (fromIntegral (wa_y wa) + dy)) float w -- | @keysMoveWindowTo (x, y) (gx, gy)@ moves the window relative -- point @(gx, gy)@ to the point @(x,y)@, where @(gx,gy)@ gives a -- position relative to the window border, i.e. @gx = 0@ is the left -- border, @gx = 1@ is the right border, @gy = 0@ is the top border, and -- @gy = 1@ the bottom border. -- -- For example, on a 1024x768 screen: -- -- > keysMoveWindowTo (512,384) (1%2, 1%2) -- center the window on screen -- > keysMoveWindowTo (1024,0) (1, 0) -- put window in the top right corner keysMoveWindowTo :: P -> G -> Window -> X () keysMoveWindowTo (x,y) (gx, gy) w = whenX (isClient w) $ withDisplay $ \d -> do io $ raiseWindow d w wa <- io $ getWindowAttributes d w io $ moveWindow d w (x - round (gx * fromIntegral (wa_width wa))) (y - round (gy * fromIntegral (wa_height wa))) float w type G = (Rational, Rational) type P = (Position, Position) -- | @keysResizeWindow (dx, dy) (gx, gy)@ changes the width by @dx@ -- and the height by @dy@, leaving the window-relative point @(gx, -- gy)@ fixed. -- -- For example: -- -- > keysResizeWindow (10, 0) (0, 0) -- make the window 10 pixels larger to the right -- > keysResizeWindow (10, 0) (0, 1%2) -- does the same, unless sizeHints are applied -- > keysResizeWindow (10, 10) (1%2, 1%2) -- add 5 pixels on each side -- > keysResizeWindow (-10, -10) (0, 1) -- shrink the window in direction of the bottom-left corner keysResizeWindow :: D -> G -> Window -> X () keysResizeWindow = keysMoveResize keysResizeWindow' -- | @keysAbsResizeWindow (dx, dy) (ax, ay)@ changes the width by @dx@ -- and the height by @dy@, leaving the screen absolute point @(ax, -- ay)@ fixed. -- -- For example: -- -- > keysAbsResizeWindow (10, 10) (0, 0) -- enlarge the window; if it is not in the top-left corner it will also be moved down and to the right. keysAbsResizeWindow :: D -> D -> Window -> X () keysAbsResizeWindow = keysMoveResize keysAbsResizeWindow' keysAbsResizeWindow' :: SizeHints -> P -> D -> D -> D -> (P,D) keysAbsResizeWindow' sh (x,y) (w,h) (dx,dy) (ax, ay) = ((round nx, round ny), (nw, nh)) where (nw, nh) = applySizeHintsContents sh (w + dx, h + dy) nx :: Rational nx = fromIntegral (ax * w + nw * (fromIntegral x - ax)) / fromIntegral w ny :: Rational ny = fromIntegral (ay * h + nh * (fromIntegral y - ay)) / fromIntegral h keysResizeWindow' :: SizeHints -> P -> D -> D -> G -> (P,D) keysResizeWindow' sh (x,y) (w,h) (dx,dy) (gx, gy) = ((nx, ny), (nw, nh)) where (nw, nh) = applySizeHintsContents sh (w + dx, h + dy) nx = round $ fromIntegral x + gx * fromIntegral w - gx * fromIntegral nw ny = round $ fromIntegral y + gy * fromIntegral h - gy * fromIntegral nh keysMoveResize :: (SizeHints -> P -> D -> a -> b -> (P,D)) -> a -> b -> Window -> X () keysMoveResize f move resize w = whenX (isClient w) $ withDisplay $ \d -> do io $ raiseWindow d w wa <- io $ getWindowAttributes d w sh <- io $ getWMNormalHints d w let wa_dim = (fromIntegral $ wa_width wa, fromIntegral $ wa_height wa) wa_pos = (fromIntegral $ wa_x wa, fromIntegral $ wa_y wa) (wn_pos, wn_dim) = f sh wa_pos wa_dim move resize io $ resizeWindow d w `uncurry` wn_dim io $ moveWindow d w `uncurry` wn_pos float w