Add X.H.Rescreen module (custom rescreen hooks)

This commit is contained in:
Tomas Janousek 2021-01-31 17:05:36 +00:00
parent f71095885f
commit 5b28f5ee54
2 changed files with 74 additions and 0 deletions

73
XMonad/Hooks/Rescreen.hs Normal file
View File

@ -0,0 +1,73 @@
-- |
-- Module : XMonad.Hooks.Rescreen
-- Copyright : (c) 2021 Tomáš Janoušek <tomi@nomi.cz>
-- License : BSD3
-- Maintainer : Tomáš Janoušek <tomi@nomi.cz>
--
-- Custom hooks for screen (xrandr) configuration changes.
--
module XMonad.Hooks.Rescreen (
-- * Usage
-- $usage
rescreenHook,
rescreenEventHook,
) where
import Control.Monad.Fix (fix)
import Control.Monad (when)
import Data.Monoid (All(..))
import XMonad
-- $usage
-- This module provides a replacement for the screen configuration change
-- handling in core that enables attaching a custom hook that can
-- restart/reposition status bars or systray.
--
-- You can use it by including the following in your @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad.Hooks.RescreenHook
--
-- defining your custom rescreen hook:
--
-- > myRescreenHook :: X ()
-- > myRescreenHook = …
--
-- and adding 'rescreenHook' to your 'xmonad' config:
--
-- > main = xmonad $ … . rescreenHook myRescreenHook . … $ def{…}
-- | Attach a custom hook when the screen configuration changes (due to
-- xrandr). Replaces the built-in rescreen handling of xmonad core with:
--
-- 1. suppress duplicate change events
-- 2. 'rescreen'
-- 3. invoke specified hook
--
-- Useful for restarting/repositioning status bars and systray.
rescreenHook :: X () -> XConfig a -> XConfig a
rescreenHook hook xConfig =
xConfig{ handleEventHook = handleEventHook xConfig <> rescreenEventHook hook }
-- | Event hook with custom rescreen hook. See 'rescreenHook' for more.
rescreenEventHook :: X () -> Event -> X All
rescreenEventHook hook ConfigureEvent{ev_event_type = t, ev_window = w} = do
isRescreen <- isRoot w
if isRescreen
then do
-- Xorg emits several ConfigureEvents after every change,
-- clear them to prevent triggering the hook multiple times
clearTypedWindowEvents w t
rescreen
hook
return (All False)
else mempty
rescreenEventHook _ _ = mempty
-- | Remove all X events of a given window and type from the event queue.
clearTypedWindowEvents :: Window -> EventType -> X ()
clearTypedWindowEvents w t = withDisplay $ \d -> io $ do
sync d False
allocaXEvent $ \e -> fix $ \again -> do
more <- checkTypedWindowEvent d w t e
when more again

View File

@ -184,6 +184,7 @@ library
XMonad.Hooks.Place XMonad.Hooks.Place
XMonad.Hooks.PositionStoreHooks XMonad.Hooks.PositionStoreHooks
XMonad.Hooks.RefocusLast XMonad.Hooks.RefocusLast
XMonad.Hooks.Rescreen
XMonad.Hooks.RestoreMinimized XMonad.Hooks.RestoreMinimized
XMonad.Hooks.ScreenCorners XMonad.Hooks.ScreenCorners
XMonad.Hooks.Script XMonad.Hooks.Script