mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 11:30:22 -07:00
This patch includes several changes, which are strictly related and cannot be recorded separately: - remove Decoraion.isDecoartion and introduce Decoration.isInStack (with the related change to LayoutHints) - in Decoration introduce useful utilities: isVisible, isInvisible, isWithin and lookFor' - MouseResize: - invisible inputOnly windows will not be created; - fix a bug in the read instance which caused a failure in the state deserialization.
133 lines
5.0 KiB
Haskell
133 lines
5.0 KiB
Haskell
{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-}
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : XMonad.Actions.MouseResize
|
|
-- Copyright : (c) 2007 Andrea Rossato
|
|
-- License : BSD-style (see xmonad/LICENSE)
|
|
--
|
|
-- Maintainer : andrea.rossato@unibz.it
|
|
-- Stability : unstable
|
|
-- Portability : unportable
|
|
--
|
|
-- A layout modifier to resize windows with the mouse by grabbing the
|
|
-- window's lower right corner.
|
|
--
|
|
-- This module must be used together with "XMonad.Layout.WindowArranger".
|
|
-----------------------------------------------------------------------------
|
|
|
|
module XMonad.Actions.MouseResize
|
|
( -- * Usage:
|
|
-- $usage
|
|
mouseResize
|
|
, MouseResize (..)
|
|
) where
|
|
|
|
import Control.Monad
|
|
import Data.Maybe
|
|
|
|
import XMonad
|
|
import XMonad.Layout.Decoration
|
|
import XMonad.Layout.LayoutModifier
|
|
|
|
import XMonad.Layout.WindowArranger
|
|
import XMonad.Util.XUtils
|
|
|
|
-- $usage
|
|
-- Usually this module is used to create layouts, but you can also use
|
|
-- it to resize windows in any layout, together with the
|
|
-- "XMonad.Layout.WindowArranger". For usage example see
|
|
-- "XMonad.Layout.SimpleFloat" or "XMonad.Layout.DecorationMadness".
|
|
--
|
|
-- You can use this module with the following in your
|
|
-- @~\/.xmonad\/xmonad.hs@:
|
|
--
|
|
-- > import XMonad.Actions.MouseResize
|
|
-- > import XMonad.Layout.WindowArranger
|
|
--
|
|
-- Then edit your @layoutHook@ by modifying a given layout:
|
|
--
|
|
-- > myLayouts = mouseResize $ windowArrange $ layoutHook defaultConfig
|
|
--
|
|
-- and then:
|
|
--
|
|
-- > main = xmonad defaultConfig { layoutHook = myLayouts }
|
|
--
|
|
-- For more detailed instructions on editing the layoutHook see:
|
|
--
|
|
-- "XMonad.Doc.Extending#Editing_the_layout_hook"
|
|
|
|
mouseResize :: l a -> ModifiedLayout MouseResize l a
|
|
mouseResize = ModifiedLayout (MR [])
|
|
|
|
data MouseResize a = MR [((a,Rectangle),Maybe a)]
|
|
instance Show (MouseResize a) where show _ = ""
|
|
instance Read (MouseResize a) where readsPrec _ s = [(MR [], s)]
|
|
|
|
instance LayoutModifier MouseResize Window where
|
|
redoLayout (MR st) _ s wrs
|
|
| [] <- st = initState >>= \nst -> return (wrs, Just $ MR nst)
|
|
| otherwise = processState >>= \nst -> return (wrs, Just $ MR nst)
|
|
where
|
|
wrs' = wrs_to_state [] . filter (isInStack s . fst) $ wrs
|
|
initState = mapM createInputWindow wrs'
|
|
processState = mapM (deleteInputWin . snd) st >> mapM createInputWindow wrs'
|
|
|
|
inputRectangle (Rectangle x y wh ht) = Rectangle (x + fi wh - 5) (y + fi ht - 5) 10 10
|
|
|
|
wrs_to_state rs ((w,r):xs)
|
|
| ir `isVisible` rs = ((w,r),Just ir) : wrs_to_state (r:ir:rs) xs
|
|
| otherwise = ((w,r),Nothing) : wrs_to_state (r: rs) xs
|
|
where ir = inputRectangle r
|
|
wrs_to_state _ [] = []
|
|
|
|
handleMess (MR s) m
|
|
| Just e <- fromMessage m :: Maybe Event = handleResize s e >> return Nothing
|
|
| Just Hide <- fromMessage m = releaseResources >> return (Just $ MR [])
|
|
| Just ReleaseResources <- fromMessage m = releaseResources >> return (Just $ MR [])
|
|
where releaseResources = mapM_ (deleteInputWin . snd) s
|
|
handleMess _ _ = return Nothing
|
|
|
|
handleResize :: [((Window,Rectangle),Maybe Window)] -> Event -> X ()
|
|
handleResize st ButtonEvent { ev_window = ew, ev_event_type = et }
|
|
| et == buttonPress
|
|
, Just (w,Rectangle wx wy _ _) <- getWin ew st = do
|
|
focus w
|
|
mouseDrag (\x y -> do
|
|
let rect = Rectangle wx wy
|
|
(max 1 . fi $ x - wx)
|
|
(max 1 . fi $ y - wy)
|
|
sendMessage (SetGeometry rect)) (return ())
|
|
|
|
where
|
|
getWin w (((win,r),tw):xs)
|
|
| Just w' <- tw
|
|
, w == w' = Just (win,r)
|
|
| otherwise = getWin w xs
|
|
getWin _ [] = Nothing
|
|
handleResize _ _ = return ()
|
|
|
|
createInputWindow :: ((Window,Rectangle), Maybe Rectangle) -> X ((Window,Rectangle),Maybe Window)
|
|
createInputWindow ((w,r),mr) = do
|
|
case mr of
|
|
Just tr -> withDisplay $ \d -> do
|
|
tw <- mkInputWindow d tr
|
|
io $ selectInput d tw (exposureMask .|. buttonPressMask)
|
|
showWindow tw
|
|
return ((w,r), Just tw)
|
|
Nothing -> return ((w,r), Nothing)
|
|
|
|
deleteInputWin :: Maybe Window -> X ()
|
|
deleteInputWin = maybe (return ()) deleteWindow
|
|
|
|
mkInputWindow :: Display -> Rectangle -> X Window
|
|
mkInputWindow d (Rectangle x y w h) = do
|
|
rw <- asks theRoot
|
|
let screen = defaultScreenOfDisplay d
|
|
visual = defaultVisualOfScreen screen
|
|
attrmask = cWOverrideRedirect
|
|
io $ allocaSetWindowAttributes $
|
|
\attributes -> do
|
|
set_override_redirect attributes True
|
|
createWindow d rw x y w h 0 0 inputOnly visual attrmask attributes
|