mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 03:20:21 -07:00
XMonad.Hooks.FadeWindows: A generalized window fading hook
This commit is contained in:
parent
4bcf636259
commit
85d6b79ab9
221
XMonad/Hooks/FadeWindows.hs
Normal file
221
XMonad/Hooks/FadeWindows.hs
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
-- |
|
||||||
|
-- Module : XMonad.Hooks.FadeWindows
|
||||||
|
-- Copyright : Brandon S Allbery KF8NH <allbery.b@gmail.com>
|
||||||
|
-- License : BSD
|
||||||
|
--
|
||||||
|
-- Maintainer : Brandon S Allbery KF8NH
|
||||||
|
-- Stability : unstable
|
||||||
|
-- Portability : unportable
|
||||||
|
--
|
||||||
|
-- A more flexible and general compositing interface than FadeInactive.
|
||||||
|
-- Windows can be selected and opacity specified by means of FadeHooks,
|
||||||
|
-- which are very similar to ManageHooks and use the same machinery.
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
module XMonad.Hooks.FadeWindows (-- * Usage
|
||||||
|
-- $usage
|
||||||
|
|
||||||
|
-- * The 'logHook' for window fading
|
||||||
|
fadeWindowsLogHook
|
||||||
|
|
||||||
|
-- * The 'FadeHook'
|
||||||
|
,FadeHook
|
||||||
|
,Opacity
|
||||||
|
,idFadeHook
|
||||||
|
|
||||||
|
-- * Predefined 'FadeHook's
|
||||||
|
,opaque
|
||||||
|
,solid
|
||||||
|
,transparent
|
||||||
|
,invisible
|
||||||
|
,transparency
|
||||||
|
,translucence
|
||||||
|
,fadeBy
|
||||||
|
,opacity
|
||||||
|
,fadeTo
|
||||||
|
|
||||||
|
-- * 'handleEventHook' for mapped/unmapped windows
|
||||||
|
,fadeWindowsEventHook
|
||||||
|
|
||||||
|
-- * 'doF' for simple hooks
|
||||||
|
,doS
|
||||||
|
|
||||||
|
-- * Useful 'Query's for 'FadeHook's
|
||||||
|
,isFloating
|
||||||
|
,isUnfocused
|
||||||
|
) where
|
||||||
|
|
||||||
|
import XMonad.Core
|
||||||
|
import XMonad.ManageHook (liftX)
|
||||||
|
import qualified XMonad.StackSet as W
|
||||||
|
|
||||||
|
import XMonad.Hooks.FadeInactive (setOpacity
|
||||||
|
,isUnfocused
|
||||||
|
)
|
||||||
|
|
||||||
|
import Control.Monad (forM_)
|
||||||
|
import Control.Monad.Reader (ask
|
||||||
|
,asks)
|
||||||
|
import Control.Monad.State (gets)
|
||||||
|
import qualified Data.Map as M
|
||||||
|
import Data.Monoid
|
||||||
|
|
||||||
|
import Graphics.X11.Xlib.Extras (Event(..))
|
||||||
|
|
||||||
|
-- $usage
|
||||||
|
-- To use this module, make sure your @xmonad@ core supports generalized
|
||||||
|
-- 'ManageHook's (check the type of 'idHook'; if it's @ManageHook@ then
|
||||||
|
-- your @xmonad@ is too old) and then add @fadeWindowsLogHook@ to your
|
||||||
|
-- 'logHook' and @fadeWindowsEventHook@ to your 'handleEventHook':
|
||||||
|
--
|
||||||
|
-- > , logHook = fadeWindowsLogHook myFadeHook
|
||||||
|
-- > , handleEventHook = fadeWindowsEventHook
|
||||||
|
-- > {- ... -}
|
||||||
|
-- >
|
||||||
|
-- > myFadeHook = composeAll [isUnfocused --> transparency 0.2
|
||||||
|
-- > , opaque
|
||||||
|
-- > ]
|
||||||
|
--
|
||||||
|
-- The above is like FadeInactive with a fade value of 0.2.
|
||||||
|
--
|
||||||
|
-- FadeHooks do not accumulate; instead, they compose from right to
|
||||||
|
-- left like 'ManageHook's, so the above example @myFadeHook@ will
|
||||||
|
-- render unfocused windows at 4/5 opacity and the focused window
|
||||||
|
-- as opaque. The 'opaque' hook above is optional, by the way, as any
|
||||||
|
-- unmatched window will be opaque by default.
|
||||||
|
--
|
||||||
|
-- This module is best used with "XMonad.Hooks.MoreManageHelpers", which
|
||||||
|
-- exports a number of Queries that can be used in either @ManageHook@
|
||||||
|
-- or @FadeHook@.
|
||||||
|
--
|
||||||
|
-- Note that you need a compositing manager such as @xcompmgr@,
|
||||||
|
-- @dcompmgr@, or @cairo-compmgr@ for window fading to work. If you
|
||||||
|
-- aren't running a compositing manager, the opacity will be recorded
|
||||||
|
-- but won't take effect until a compositing manager is started.
|
||||||
|
--
|
||||||
|
-- For more detailed instructions on editing the 'logHook' see:
|
||||||
|
--
|
||||||
|
-- "XMonad.Doc.Extending#The_log_hook_and_external_status_bars"
|
||||||
|
--
|
||||||
|
-- For more detailed instructions on editing the 'handleEventHook',
|
||||||
|
-- see:
|
||||||
|
--
|
||||||
|
-- "XMonad.Doc.Extending#Editing_the_event_hook"
|
||||||
|
-- (which sadly doesnt exist at the time of writing...)
|
||||||
|
--
|
||||||
|
-- /WARNING:/ This module is very good at triggering bugs in
|
||||||
|
-- compositing managers. Symptoms range from windows not being
|
||||||
|
-- repainted until the compositing manager is restarted or the
|
||||||
|
-- window is unmapped and remapped, to the machine becoming sluggish
|
||||||
|
-- until the compositing manager is restarted (at which point a
|
||||||
|
-- popup/dialog will suddenly appear; apparently it's getting into
|
||||||
|
-- a tight loop trying to fade the popup in). I find it useful to
|
||||||
|
-- have a key binding to restart the compositing manager; for example,
|
||||||
|
--
|
||||||
|
-- main = xmonad $ defaultConfig {
|
||||||
|
-- {- ... -}
|
||||||
|
-- }
|
||||||
|
-- `additionalKeysP`
|
||||||
|
-- [("M-S-4",spawn "killall xcompmgr; sleep 1; xcompmgr -cCfF &")]
|
||||||
|
-- {- ... -}
|
||||||
|
-- ]
|
||||||
|
--
|
||||||
|
-- (See "XMonad.Util.EZConfig" for 'additionalKeysP'.)
|
||||||
|
|
||||||
|
-- a window opacity to be carried in a Query. OEmpty is sort of a hack
|
||||||
|
-- to make it obay the monoid laws
|
||||||
|
data Opacity = Opacity Rational | OEmpty
|
||||||
|
|
||||||
|
instance Monoid Opacity where
|
||||||
|
mempty = OEmpty
|
||||||
|
r `mappend` OEmpty = r
|
||||||
|
_ `mappend` r = r
|
||||||
|
|
||||||
|
-- | A FadeHook is similar to a ManageHook, but records window opacity.
|
||||||
|
type FadeHook = Query Opacity
|
||||||
|
|
||||||
|
-- | Render a window fully opaque.
|
||||||
|
opaque :: FadeHook
|
||||||
|
opaque = doS (Opacity 1)
|
||||||
|
|
||||||
|
-- | Render a window fully transparent.
|
||||||
|
transparent :: FadeHook
|
||||||
|
transparent = doS (Opacity 0)
|
||||||
|
|
||||||
|
-- | Specify a window's transparency.
|
||||||
|
transparency :: Rational -- ^ The window's transparency as a fraction.
|
||||||
|
-- @transparency 1@ is the same as 'transparent',
|
||||||
|
-- whereas @transparency 0@ is the same as 'opaque'.
|
||||||
|
-> FadeHook
|
||||||
|
transparency = doS . Opacity . (1-) . clampRatio
|
||||||
|
|
||||||
|
-- | Specify a window's opacity; this is the inverse of 'transparency'.
|
||||||
|
opacity :: Rational -- ^ The opacity of a window as a fraction.
|
||||||
|
-- @opacity 1@ is the same as 'opaque',
|
||||||
|
-- whereas @opacity 0@ is the same as 'transparent'.
|
||||||
|
-> FadeHook
|
||||||
|
opacity = doS . Opacity . clampRatio
|
||||||
|
|
||||||
|
fadeTo, translucence, fadeBy :: Rational -> FadeHook
|
||||||
|
-- ^ An alias for 'transparency'.
|
||||||
|
fadeTo = transparency
|
||||||
|
-- ^ An alias for 'transparency'.
|
||||||
|
translucence = transparency
|
||||||
|
-- ^ An alias for 'transparency'.
|
||||||
|
fadeBy = opacity
|
||||||
|
|
||||||
|
invisible, solid :: FadeHook
|
||||||
|
-- ^ An alias for 'transparent'.
|
||||||
|
invisible = transparent
|
||||||
|
-- ^ An alias for 'opaque'.
|
||||||
|
solid = opaque
|
||||||
|
|
||||||
|
-- | Like 'doF', but usable with 'ManageHook'-like hooks that
|
||||||
|
-- aren't 'Query' wrapped around transforming functions ('Endo').
|
||||||
|
doS :: Monoid m => m -> Query m
|
||||||
|
doS = return
|
||||||
|
|
||||||
|
-- | The identity 'FadeHook', which renders windows 'opaque'.
|
||||||
|
idFadeHook :: FadeHook
|
||||||
|
idFadeHook = opaque
|
||||||
|
|
||||||
|
-- | A Query to determine if a window is floating.
|
||||||
|
isFloating :: Query Bool
|
||||||
|
isFloating = ask >>= \w -> liftX . gets $ M.member w . W.floating . windowset
|
||||||
|
|
||||||
|
-- boring windows can't be seen outside of a layout, so we watch messages with
|
||||||
|
-- a dummy LayoutModifier and stow them in a persistent bucket. this is not
|
||||||
|
-- entirely reliable given that boringAuto still isn't observable; we just hope
|
||||||
|
-- those aren't visible and won;t be affected anyway
|
||||||
|
-- @@@ punted for now, will be a separate module. it's still slimy, though
|
||||||
|
|
||||||
|
-- | A 'logHook' to fade windows under control of a 'FadeHook', which is
|
||||||
|
-- similar to but not identical to 'ManageHook'.
|
||||||
|
fadeWindowsLogHook :: FadeHook -> X ()
|
||||||
|
fadeWindowsLogHook h = withWindowSet $ \s -> do
|
||||||
|
let visibleWins = (W.integrate' . W.stack . W.workspace . W.current $ s) ++
|
||||||
|
concatMap (W.integrate' . W.stack . W.workspace) (W.visible s)
|
||||||
|
forM_ visibleWins $ \w -> do
|
||||||
|
o <- userCodeDef (Opacity 1) (runQuery h w)
|
||||||
|
setOpacity w $ case o of
|
||||||
|
OEmpty -> 0.93
|
||||||
|
Opacity r -> r
|
||||||
|
|
||||||
|
-- | A 'handleEventHook' to handle fading and unfading of newly mapped
|
||||||
|
-- or unmapped windows; this avoids problems with layouts such as
|
||||||
|
-- "XMonad.Layout.Full" or "XMonad.Layout.Tabbed". This hook may
|
||||||
|
-- also be useful with "XMonad.Hooks.FadeInactive".
|
||||||
|
fadeWindowsEventHook :: Event -> X All
|
||||||
|
fadeWindowsEventHook (MapNotifyEvent {}) =
|
||||||
|
-- we need to run the fadeWindowsLogHook. only one way...
|
||||||
|
asks config >>= logHook >> return (All True)
|
||||||
|
fadeWindowsEventHook _ = return (All True)
|
||||||
|
|
||||||
|
-- A utility to clamp opacity fractions to the range (0,1)
|
||||||
|
clampRatio :: Rational -> Rational
|
||||||
|
clampRatio r | r >= 0 && r <= 1 = r
|
||||||
|
| r < 0 = 0
|
||||||
|
| otherwise = 1
|
@ -143,6 +143,7 @@ library
|
|||||||
XMonad.Hooks.DynamicLog
|
XMonad.Hooks.DynamicLog
|
||||||
XMonad.Hooks.EwmhDesktops
|
XMonad.Hooks.EwmhDesktops
|
||||||
XMonad.Hooks.FadeInactive
|
XMonad.Hooks.FadeInactive
|
||||||
|
XMonad.Hooks.FadeWindows
|
||||||
XMonad.Hooks.FloatNext
|
XMonad.Hooks.FloatNext
|
||||||
XMonad.Hooks.ICCCMFocus
|
XMonad.Hooks.ICCCMFocus
|
||||||
XMonad.Hooks.InsertPosition
|
XMonad.Hooks.InsertPosition
|
||||||
|
Loading…
x
Reference in New Issue
Block a user