mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-18 19:10:21 -07:00
All hints are applied in one single commit, as a commit per hint would result in 80+ separate commits—tihs is really just too much noise. Related: https://github.com/xmonad/xmonad-contrib/issues/537
104 lines
4.6 KiB
Haskell
104 lines
4.6 KiB
Haskell
----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : XMonad.Hooks.PositionStoreHooks
|
|
-- Copyright : (c) Jan Vornberger 2009
|
|
-- License : BSD3-style (see LICENSE)
|
|
--
|
|
-- Maintainer : jan.vornberger@informatik.uni-oldenburg.de
|
|
-- Stability : unstable
|
|
-- Portability : not portable
|
|
--
|
|
-- This module contains two hooks for the
|
|
-- PositionStore (see "XMonad.Util.PositionStore") - a ManageHook and
|
|
-- an EventHook.
|
|
--
|
|
-- The ManageHook can be used to fill the PositionStore with position and size
|
|
-- information about new windows. The advantage of using this hook is, that the
|
|
-- information is recorded independent of the currently active layout. So the
|
|
-- floating shape of the window can later be restored even if it was opened in a
|
|
-- tiled layout initially.
|
|
--
|
|
-- For windows, that do not request a particular position, a random position will
|
|
-- be assigned. This prevents windows from piling up exactly on top of each other.
|
|
--
|
|
-- The EventHook makes sure that windows are deleted from the PositionStore
|
|
-- when they are closed.
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
module XMonad.Hooks.PositionStoreHooks (
|
|
-- * Usage
|
|
-- $usage
|
|
positionStoreManageHook,
|
|
positionStoreEventHook
|
|
) where
|
|
|
|
import XMonad
|
|
import XMonad.Prelude
|
|
import qualified XMonad.StackSet as W
|
|
import XMonad.Util.PositionStore
|
|
import XMonad.Hooks.ManageDocks
|
|
import XMonad.Layout.Decoration
|
|
|
|
import System.Random(randomRIO)
|
|
import qualified Data.Set as S
|
|
|
|
-- $usage
|
|
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
|
|
--
|
|
-- > import XMonad.Hooks.PositionStoreHooks
|
|
--
|
|
-- and adding 'positionStoreManageHook' to your 'ManageHook' as well
|
|
-- as 'positionStoreEventHook' to your event hooks. To be accurate
|
|
-- about window sizes, the module needs to know if any decoration is in effect.
|
|
-- This is specified with the first argument: Supply 'Nothing' for no decoration,
|
|
-- otherwise use 'Just def' or similar to inform the module about the
|
|
-- decoration theme used.
|
|
--
|
|
-- > myManageHook = positionStoreManageHook Nothing <+> manageHook def
|
|
-- > myHandleEventHook = positionStoreEventHook
|
|
-- >
|
|
-- > main = xmonad def { manageHook = myManageHook
|
|
-- > , handleEventHook = myHandleEventHook
|
|
-- > }
|
|
--
|
|
|
|
positionStoreManageHook :: Maybe Theme -> ManageHook
|
|
positionStoreManageHook mDecoTheme = ask >>= liftX . positionStoreInit mDecoTheme >> idHook
|
|
|
|
positionStoreInit :: Maybe Theme -> Window -> X ()
|
|
positionStoreInit mDecoTheme w = withDisplay $ \d -> do
|
|
let decoH = maybe 0 decoHeight mDecoTheme -- take decoration into account, which - in its current
|
|
-- form - makes windows smaller to make room for it
|
|
wa <- io $ getWindowAttributes d w
|
|
ws <- gets windowset
|
|
arbitraryOffsetX <- randomIntOffset
|
|
arbitraryOffsetY <- randomIntOffset
|
|
if (wa_x wa == 0) && (wa_y wa == 0)
|
|
then do
|
|
let sr@(Rectangle srX srY _ _) = screenRect . W.screenDetail . W.current $ ws
|
|
modifyPosStore (\ps -> posStoreInsert ps w
|
|
(Rectangle (srX + fi arbitraryOffsetX)
|
|
(srY + fi arbitraryOffsetY)
|
|
(fi $ wa_width wa)
|
|
(decoH + fi (wa_height wa))) sr )
|
|
else do
|
|
sc <- fromMaybe (W.current ws) <$> pointScreen (fi $ wa_x wa) (fi $ wa_y wa)
|
|
let sr = screenRect . W.screenDetail $ sc
|
|
sr' <- fmap ($ sr) (calcGap $ S.fromList [minBound .. maxBound]) -- take docks into account, accepting
|
|
-- a somewhat unfortunate inter-dependency
|
|
-- with 'XMonad.Hooks.ManageDocks'
|
|
modifyPosStore (\ps -> posStoreInsert ps w
|
|
(Rectangle (fi $ wa_x wa) (fi (wa_y wa) - fi decoH)
|
|
(fi $ wa_width wa) (decoH + fi (wa_height wa))) sr' )
|
|
where
|
|
randomIntOffset :: X Int
|
|
randomIntOffset = io $ randomRIO (42, 242)
|
|
|
|
positionStoreEventHook :: Event -> X All
|
|
positionStoreEventHook DestroyWindowEvent{ev_window = w, ev_event_type = et} = do
|
|
when (et == destroyNotify) $
|
|
modifyPosStore (`posStoreRemove` w)
|
|
return (All True)
|
|
positionStoreEventHook _ = return (All True)
|