xmonad-config/bin/xit-event.hs

53 lines
1.8 KiB
Haskell

-- | Send a special event as a signal to the window manager
-- Specifically, this is meant to be run after applications exit which
-- will allow xmonad to react to processes closing. It takes two
-- arguments: a string called the "magic string" up to 5 characters
-- and a string up to 15 characters called the "tag." These will be
-- concatenated and sent to xmonad in a ClientRequest event of type
-- BITMAP (which hopefully will never do anything) to the root window.
-- Operationally, the magic string is meant to be used to
-- differentiate this event and the tag is meant to be a signal to be
-- read by xmonad.
import Graphics.X11.Types
import Graphics.X11.Xlib.Atom
import Graphics.X11.Xlib.Display
import Graphics.X11.Xlib.Event
import Graphics.X11.Xlib.Extras
import System.Environment
import System.Exit
main :: IO ()
main = getArgs >>= parse
parse :: [String] -> IO ()
parse [magic, tag] = send magic tag >> exitSuccess
parse _ = exitFailure
send :: String -> String -> IO ()
send magic tag = do
dpy <- openDisplay ""
root <- rootWindow dpy $ defaultScreen dpy
allocaXEvent $ \e -> do
setEventType e clientMessage
-- NOTE: This function is written such that the penultimate
-- argument represents the first 40 bits of the 160 bit data
-- field, and it also only takes a decimal digit, which means the
-- string to be stored in the data field needs to be converted to
-- its decimal equivalent. The penultimate argument will be used
-- for the magic string and the last will be used for the tag.
setClientMessageEvent e root bITMAP 8 m t
sendEvent dpy root False substructureNotifyMask e
flush dpy
where
m = str2digit magic
t = str2digit tag
str2digit :: (Num a) => String -> a
str2digit = fromIntegral
. sum
. map (\(p, n) -> n * 256 ^ p)
. zip [0 :: Int ..]
. map fromEnum