I'm still struggling with Haskell's X11 binding. Now, I want to detect the event of user closing the window. My best attempt so far:
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras
import Control.Concurrent (threadDelay)
import Data.Bits
main :: IO ()
main = do
dpy <- openDisplay ""
let dflt = defaultScreen dpy
border = blackPixel dpy dflt
background = whitePixel dpy dflt
rootw <- rootWindow dpy dflt
win <- createSimpleWindow dpy rootw 0 0 300 200 1 border background
setTextProperty dpy win "Hello World" wM_NAME
mapWindow dpy win
moveWindow dpy win 0 0
selectInput dpy win (structureNotifyMask .|. exposureMask)
updateWin dpy win
updateWin :: Display -> Window -> IO ()
updateWin dpy win = do
sync dpy True
allocaXEvent $ \e -> do
nextEvent dpy e
ev <- getEvent e
putStrLn $ eventName ev
threadDelay (1000000)
updateWin dpy win
But instead of getting the event, I get the following output:
ConfigureNotify
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
after 26 requests (25 known processed) with 5 events remaining.
What is causing this? What would be the right way to deal with it?
You need to watch ClientMessage events. There's no mask and no need to select them, just detect them and destroy the window. You also need to set WM_DELETE_WINDOW protocol. See e.g. here. Look for ClientMessage and WM_DELETE_WINDOW.
At some point you will want to intercept other client messages apart from WM_DELETE_WINDOW. You will need to examine ClientMessage contents, not just the type, but for now it's not needed.