X11 窗口定位和窗口管理器交互的奇怪问题

问题描述 投票:0回答:1

我有一个 Linux、X11 应用程序,带有主窗口 (W0) 和浮动工具/调色板窗口 (Wt)。

Wt 必须始终位于 W0 上方,并且首次显示时,它必须出现在 W0 的右上角,以免视图与 W0 重叠。

此外,Wt 必须由窗口管理器用标题栏和可调整大小的边框进行装饰。

Wt 设置了以下属性:

WM_TRANSIENT_FOR(WINDOW): window id # 0x5600002  <------ This is the id of the W0 window!
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_UTILITY
_NET_WM_STATE(ATOM) = _NET_WM_STATE_SKIP_PAGER, _NET_WM_STATE_SKIP_TASKBAR

问题出在 WM_TRANSIENT_FOR 属性上。当我不设置它时,窗口被正确定位,但是当主窗口被激活时,Wt窗口落后并被主窗口重叠。

当我设置 WM_TRANSIENT_FOR 时,窗口始终正确地位于 W0 上方,但窗口管理器将 Wt 放置在 W0 的中心,忽略传递给 CreateWindow 请求的 x 和 y。

我尝试了不同的技巧,为 _NET_WM_WINDOW_TYPE 属性设置不同的值,使用 WM_NORMAL_HINTS,设置 PPosition (似乎已弃用),但一切都是徒劳。

最后,作为绝望的行为,我尝试在窗口映射(并由 WM 处理)后设置 WM_TRANSIENT_FOR。像这样:

Create Wt
Map Wt
Set WM_TRANSIENT_FOR to Wt

而且这个伎俩根本不起作用。

但后来我尝试在映射窗口和 WM_TRANSIENT_FOR 属性集之间放置一些暂停:

Create Wt
Map Wt
Sleep(1ms)
Set WM_TRANSIENT_FOR to Wt

最后,这个技巧完成了工作 - Wt 位置正确,并且窗口管理器不会干扰它居中。

但是,我对这个“解决方案”并不是很满意。它非常丑陋,根本不应该使用。

所以,问题是:

  1. 这个问题的正确解决方案是什么。如何同时设置 WM_TRANSIENT_FOR 和窗口位置以及窗口管理器而不使其与主窗口居中?

  2. 为什么这个小停顿会如此彻底地改变窗口管理器的行为?最后,整个 X11 协议不应该对某些网络延迟可能导致的客户端-服务器通信延迟如此敏感。

窗口管理器是XFWM,但我不确定它是否那么重要。将使用其他 WM 进行一些实验,如果存在差异,将编辑问题。

附注请不要推荐 Qt、GTK、FLTK 等任何工具包。我知道他们的存在。

linux x11 xlib xcb icccm
1个回答
0
投票

这个问题的正确解决方案是什么。

您不会想听到这个,但正确的解决方案是将窗口管理留给窗口管理器。不要尝试这样做。

为什么小停顿会如此彻底地改变窗口管理器的行为?

问题是“当窗口管理器开始管理窗口时,窗口的状态是什么”。如果您在发送

MapWindow
请求后立即更改某些状态,则此状态更改可能会在 WM 查询窗口状态之前应用。如果您稍等一下,此状态更改只会在之后应用。

我尝试在窗口映射后设置WM_TRANSIENT_FOR

我认为(但不确定)设置

WM_TRANSIENT_FOR
仅在映射窗口之前才有意义。

我有一个 Linux、X11 应用程序,带有主窗口 (W0) 和浮动工具/调色板窗口 (Wt)。 Wt 必须始终高于 W0。

从我的头脑中,我不知道任何属性/简单的解决方案来做到这一点。

我刚刚打开

gimp
并取消固定一些工具栏。用
xprop
查看这个窗口没有发现任何特殊/神奇的属性。我不知道 Gimp / GTK 在主窗口上方有这个工具栏。如果您能弄清楚这一点,这可能会对您有所帮助。

但是,没有任何保证。来自 ICCCM § 4.1.5:

在任何情况下,窗口管理器都可以根据自己认为合适的方式自由地将窗口放置在堆栈中,因此客户端不应依赖于接收他们请求的堆栈顺序。

© www.soinside.com 2019 - 2024. All rights reserved.