Haskell中订阅X11事件代码挂起,求排查原因
问题分析与解决方案
你的代码挂起无响应的核心原因是错误设置了X11窗口的事件监听掩码,具体有两个关键问题:
1. 属性修改掩码与事件掩码混淆
changeWindowAttributes的第三个参数是属性选择掩码(用来告知X服务器要修改窗口的哪些属性),而非直接传事件掩码。你需要传入cWEventMask来指定要修改窗口的eventMask属性,同时在SetWindowAttributes结构体中设置实际要监听的事件类型掩码。
2. 未正确配置事件监听的结构体字段
你没有给SetWindowAttributes结构体的eventMask字段赋值,导致X服务器从未收到你要监听特定事件的指令,nextEvent会一直阻塞等待不存在的事件。
修正后的代码(监听活动窗口切换)
对应原方案的逻辑(监听根窗口_NET_ACTIVE_WINDOW属性变化):
import Graphics.X11.Xlib import Foreign.Marshal.Alloc (alloca) main :: IO () main = do disp <- openDisplay "" let root = defaultRootWindow disp -- 正确配置根窗口的事件监听掩码 allocaSetWindowAttributes $ \swaPtr -> do set_swa_event_mask swaPtr propertyChangeMask changeWindowAttributes disp root cWEventMask swaPtr -- 等待并打印事件类型 allocaXEvent $ \e -> do nextEvent disp e eventType <- get_event_type e putStrLn $ "收到事件:" ++ show eventType closeDisplay disp
关键修改说明
set_swa_event_mask swaPtr propertyChangeMask:给结构体的eventMask字段赋值,指定要监听属性变化事件(对应活动窗口切换时的_NET_ACTIVE_WINDOW属性更新)。changeWindowAttributes disp root cWEventMask swaPtr:告知X服务器,要修改根窗口的eventMask属性,使用结构体中配置的掩码。- 新增
closeDisplay disp:释放X11显示资源,避免内存泄漏。
如果需要监听焦点切换事件(FocusIn/FocusOut),只需将propertyChangeMask替换为focusChangeMask即可。
内容的提问来源于stack exchange,提问作者radrow
相关产品推荐
相关产品推荐

