重父化窗口管理器中如何设置窗口实际x、y坐标,修复Firefox等应用偏移问题
问题根因
- 重父化窗口管理器会为客户端窗口创建父框架窗口,你移动的是外层框架,客户端窗口在父框架内的相对坐标始终未发生变化,默认不会触发客户端的
ConfigureNotify事件。 - Firefox、GTK系应用不会主动实时查询自身相对于根窗口的坐标,只会在内部缓存该值,仅当收到
ConfigureNotify事件时才会刷新缓存重新计算坐标,这就是菜单出现偏移的核心原因。 - 你设置的
_NET_FRAME_EXTENTS仅用于告知客户端框架装饰的边距大小,和窗口位置同步逻辑无关,因此无法解决该问题。
合规解决方案
不需要调用configure_window修改客户端窗口属性,也不需要用resize hack,你只需要主动向客户端发送合成的ConfigureNotify事件即可,这是ICCCM、EWMH规范中明确要求重父化WM实现的逻辑:
当你移动外层框架窗口后,构造一个ConfigureNotify事件发送给对应的客户端窗口,事件参数配置如下:
x/y:填客户端窗口相对于根窗口的绝对坐标width/height:填客户端窗口当前的实际宽高(不需要修改,和当前值保持一致即可)border_width:填0override_redirect:设为False
该操作仅为事件通知,不会修改任何窗口的实际属性,完全不会触发窗口在框架内偏移的问题。
resize hack生效的原理
你临时调整窗口大小再恢复的操作,本质是触发了WM向客户端发送带最新根坐标的ConfigureNotify事件,客户端收到后刷新了自身的坐标缓存,所以菜单位置恢复正常,和修改尺寸的操作本身无关,核心是ConfigureNotify事件的通知作用。
内容的提问来源于stack exchange,提问作者gsb
相关产品推荐
相关产品推荐

