【问题标题】:Reparenting wm and BadWindow errors重设 wm 和 BadWindow 错误
【发布时间】:2023-03-06 17:29:01
【问题描述】:

我正在用 XCB 和 C++ 编写一个重父窗口管理器:http://ix.io/3yNo

目前它工作得很好,但偶尔当我关闭一个窗口时,该应用程序的所有窗口都会关闭,因为进程以 BadWindow 退出。例如,如果我打开了几个 xfce4 终端窗口,它们都由一个进程管理,然后我关闭了一个,有时应用程序会关闭并且我会收到 BadWindow (invalid window parameter) 错误(在应用程序中,而不是我的 wm)。非常有趣的是,这不是可重现的,而是一种罕见的情况,可能是由于 X11 的异步特性,报告错误和关闭窗口之间的竞争条件。我不知道从哪里开始调试,有什么提示吗?我有点怀疑它可能是 Unmap O 中的东西

【问题讨论】:

  • 不要在链接上放任何重要的东西,因为这个问题包含零代码但指的是代码,我假设这就是链接上的内容。这非常重要。链接腐烂,这会导致问题过于依赖“无用”链接。另外,这里有很多人不会用 10 英尺的鼠标电缆接触到未知站点的链接,因为我们不想找出隐藏在另一边的困难的方式。如果您有太多代码要在这里发布,那就是minimal reproducible examples 的用途。
  • 嗯,那和minimal reproducible example 描述了一种强大的调试技术,如果遵循这种技术,通常会很快结束未提出的问题。
  • 我无法创建一个最小的可重现示例,真的,因为这个问题根本无法重现。我将代码的相关部分放在问题中。
  • 那可能不会有多大好处。如果我们无法重现,那么发现错误的几率就会大大降低。如果您只发布部分代码,几率会更低。例如,如果您不知道错误是什么,您如何确定什么是相关的或不相关的?
  • 是的,问题在于 X11 的异步特性,因此我可以在错误发生时或 2 小时后立即得到错误。我需要弄清楚如何迫使错误立即发生,通过某种方式同步 X 服务器上的所有内容。

标签: c++ x11 xcb


【解决方案1】:

您的链接包含近 500 行代码。我不会试图完全理解这一点。相反,我只是随机猜测。

auto window_manager::handle_unmap_notify(xcb_unmap_notify_event_t *ev) -> void {
  if (unmap_ignore > 0) {
    unmap_ignore--;
    return;
  }
  client *cl = nullptr;
  size_t idx = 0;
  for (client &c : clients) {
    if (c.window == ev->window) {
      cl = &c;
      break;
    }
    idx++;
  }
  if (not cl)
    return;
  xcb_destroy_window(conn, cl->frame);
  clients.erase(clients.begin() + idx);
}

你正在摧毁不属于你的窗户。当窗口的所有者下次访问它时,会得到一个BadWindow 错误。

相反,您应该检查窗口的WM_PROTOCOLS 属性并检查WM_DELETE_WINDOW。如果存在,您应该向窗口发送WM_DELETE_WINDOW 消息。参见 ICCCM § 4.2.8.1:https://tronche.com/gui/x/icccm/sec-4.html#s-4.2.8.1

【讨论】:

  • 感谢您的回答!我认为这不是问题,因为我拥有cl->frame,因为我创建了它。我不拥有的是ev->window
  • 然而,这里的问题可能是,即使客户端取消映射窗口,它也希望窗口存在并准备好绘制。当我销毁 cl->frame 时,我随后也会销毁 ev->window,因为它是框架窗口的子窗口。我会尝试切换到 xcb_unmap_window。
  • 啊,是的,销毁一个窗口也会销毁所有子窗口。
猜你喜欢
  • 2014-10-10
  • 2014-01-19
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多