mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-08-01 12:41:52 -07:00
Commitsd638dc8b
anda5e87e38
introduced a per-AvoidStruts-instance strut cache that a) didn't get initialized at startup, b) didn't get reinitialized after layout reset and c) didn't get updates if it wasn't the active layout, for example when layoutHook = avoidStruts tall ||| avoidStruts (mirror tall) a) + b) could be fixed by using the docksStartupHook introduced in28e9f8bc
, although this wasn't documented and having to call docksStartupHook after setLayout is far from obvious. By moving the strut cache from AvoidStruts instances to a global state, b) and c) are fixed. One still has to invoke the docksStartupHook for a), and this will be addressed in the next commit.
107 lines
4.6 KiB
Haskell
107 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 qualified XMonad.StackSet as W
|
|
import XMonad.Util.PositionStore
|
|
import XMonad.Hooks.ManageDocks
|
|
import XMonad.Layout.Decoration
|
|
|
|
import System.Random(randomRIO)
|
|
import Control.Applicative((<$>))
|
|
import Control.Monad(when)
|
|
import Data.Maybe
|
|
import Data.Monoid
|
|
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) $ do
|
|
modifyPosStore (\ps -> posStoreRemove ps w)
|
|
return (All True)
|
|
positionStoreEventHook _ = return (All True)
|