0

I tried mimicking this Python solution in Haskell using XMonad's X11 library, but unfortunately my code just hangs and does not react when I trigger events by switching focused windows:

disp <- X11.openDisplay ""
let root = X11.defaultRootWindow disp
X11.allocaSetWindowAttributes $ \swaPtr ->
    X11.changeWindowAttributes disp root X11.propertyChangeMask swaPtr
allocaXEvent $ \e -> nextEvent disp e

This code never terminates, but the Python equivalent normally catches X events. What is wrong here?

radrow
  • 6,419
  • 4
  • 26
  • 53
  • My X11-fu is very rusty, but I guess you need to use `set_event_mask :: Ptr SetWindowAttributes -> EventMask -> IO ()` to set the `propertyChangeMask` bit. Then, you must call `X11.changeWindowAttributes disp root X11.cWEventMask swaPtr`. It is very unfortunate that the two `Mask`s (attribute and event masks) have the same Haskell type, which misled you -- a type error would have helped here. – chi Mar 05 '23 at 20:53
  • Okay Chi, it worked, many thanks for finding this. You can post it as an answer and I will accept it. – radrow Mar 06 '23 at 10:36

1 Answers1

1

Unlike the python code you linked, the Haskell X11 library from XMonad mimics the C library closely. What we want to do here is:

  • Call changeWindowAttributes specifying the attribute(s) we want to change. Here we want to specify the "event mask" attribute.
  • Before that call, write inside swaPtr the actual event mask we want to set, using set_event_mask :: Ptr SetWindowAttributes -> EventMask -> IO ().

The final code should read like:

X11.allocaSetWindowAttributes $ \swaPtr ->
    X11.set_event_mask swaPtr X11.propertyChangeMask
    X11.changeWindowAttributes disp root X11.cWEventMask swaPtr

Minor digression: it is very unfortunate that X11.propertyChangeMask and X11.cWEventMask have the same type in C, and further also have the same type in Haskell. A newtype wrapper here would have prevented your original code, that tries to pass an event mask as an attribute mask. Arguably, even in C one would have used a lightweight struct EventMask { unsigned long em; } to prevent similar type confusion. For some reason (which I can't fathom), C libraries often abstain to pass structs as parameters, as if they still wanted to be compatible with pre-ISO, pre-ANSI, K&R C, even when they are created in much more modern times.

chi
  • 111,837
  • 3
  • 133
  • 218