【问题标题】:Drawing on windows with 32-bit color depth在具有 32 位色深的窗口上绘图
【发布时间】:2021-12-05 01:13:09
【问题描述】:

由于某种原因,在我的重设 WM 中,我根本无法在深度为 32 的 X11 窗口上绘图。我已经尝试使用 Xft 来绘制文本、绘制矩形、绘制文本的内置功能......在深度 32 的窗口上什么都没有显示。这就是我使用 X11rb 库绘制窗口的方式:

let win_aux = xproto::CreateWindowAux::new()
            .event_mask(
                xproto::EventMask::EXPOSURE
                    | xproto::EventMask::SUBSTRUCTURE_REDIRECT
                    | xproto::EventMask::SUBSTRUCTURE_NOTIFY
                    | xproto::EventMask::BUTTON_PRESS
                    | xproto::EventMask::BUTTON_RELEASE
                    | xproto::EventMask::POINTER_MOTION
                    | xproto::EventMask::ENTER_WINDOW
                    | xproto::EventMask::PROPERTY_CHANGE,
            )
            .background_pixel(self.config.background_pixel)
            .border_pixel(self.config.active_border_pixel)
            .colormap(attr.colormap);
        self.conn.create_window(
            geom.depth,
            frame_win,
            screen.root,
            geom.x,
            geom.y,
            geom.width,
            geom.height + self.config.title_height as u16,
            self.config.border_width as u16,
            xproto::WindowClass::INPUT_OUTPUT,
            attr.visual,
            &win_aux,
        )?;
        self.conn.grab_server()?.check()?;
        self.conn
            .change_save_set(xproto::SetMode::INSERT, ev.window)?
            .check()?;
        self.conn
            .reparent_window(ev.window, frame_win, 0, self.config.title_height as i16)?
            .check()?;
        self.conn.map_window(ev.window)?.check()?;
        self.conn.map_window(frame_win)?.check()?;

我该如何解决这个问题?

【问题讨论】:

  • 我的怀疑是唯一不同的东西一定是独特的平局,因此它一定是一个问题。
  • 无论您是否使用 Xft,看起来都会发生这种情况;这个问题通常只是绘制到 32 位窗口。
  • 如何绘制到窗口?我认为核心协议最终应该总是使用零的 alpha,所以在你的窗口中“一堆洞”。您可以尝试将背景像素设置为“可见”(0xffff0000 或其他),然后检查您的绘图是否在其中“打孔”。
  • 另外:您的代码示例显示了使用 x11rb 的 Rust 代码。您的问题说您使用 Xft(AFAIK 这个库仅适用于 Xlib),并且您的标签说您正在使用 xcb。你在用什么?
  • 最初,我使用 Xft 并与 xlib 进行交互。后来我意识到框架窗口上没有绘图原语,所以我编辑了这个问题以使其更通用。我的背景颜色确实有 FF 的 alpha,但我也会尝试使用该颜色。谢谢!

标签: x11


【解决方案1】:

我还没有完全弄清楚发生了什么,但是我在xtrace 下运行了您的代码并发现了这个:

000:<:005c: 20: RENDER-Request(139,4): CreatePicture pid=0x00200001 drawable=0x00200002 format=0x00000029 values={}
000:<:005d: 16: Request(53): CreatePixmap depth=0x20 pid=0x00200003 drawable=0x0000051f width=1 height=1
000:<:005e: 24: RENDER-Request(139,4): CreatePicture pid=0x00200004 drawable=0x00200003 format=0x00000025 values={repeat=true(0x01)}
000:<:005f:  8: Request(54): FreePixmap drawable=0x00200003
000:>:005c:Error 8=Match: major=139, minor=4, bad=0x00000029, seq=005c

因此,您正在执行的操作会导致错误。我想这也解释了丢失的图纸。

所以,我的第一个建议是不要默默地忽略错误:

diff --git a/src/wm.rs b/src/wm.rs
index 68e43f5..bc95d20 100644
--- a/src/wm.rs
+++ b/src/wm.rs
@@ -240,7 +240,10 @@ where
             let ev = match self.conn.wait_for_event() {
                 Ok(ev) => ev,
 
-                Err(_) => continue,
+                Err(e) => {
+                    eprintln!("Error: {:?}", e);
+                    continue;
+                }
             };
             let _ = self.dispatch_event(&ev);
         }
@@ -293,6 +296,7 @@ where
             protocol::Event::DestroyNotify(ev) => self.handle_destroy_notify(ev)?,
             protocol::Event::ClientMessage(ev) => self.handle_client_message(ev)?,
             protocol::Event::ConfigureNotify(ev) => self.handle_configure_notify(ev)?,
+            protocol::Event::Error(ev) => eprintln!("X11 error: {:?}", ev),
             _ => {}
         }
         Ok(())

(这里只需要进行第二次更改,但我是第一次遇到第一个,后来才发现我错了。)

我不太确定第二个问题是什么,但我猜应该是以下代码:

xft::XftDrawCreate(
    self.xlib_conn,
    frame_win.into(),
    xlib::XDefaultVisual(self.xlib_conn, 0),
    xlib::XDefaultColormap(self.xlib_conn, 0),
)

在这里,您告诉 xft 您的框架窗口使用屏幕的默认视觉和颜色图。但是,对于 depth=32 的窗口,这是不可能的(我检查过 - 在这种情况下,您的框架窗口也是 depth=32)。

所以...您必须以某种方式为 Xft 提供正确的视觉效果,并为 Xft 提供颜色映射。显然,您使用GetWindowAttributes 请求创建具有与包含的客户端窗口相同的值的框架窗口。

所以,现在您必须以某种方式将此可视 XID 转换为 Xlib Visual* 指针,这听起来像是一些毛茸茸的代码......

【讨论】:

  • 谢谢。我试过这样:hastebin.com/rowulorojo.rust;更改颜色图不会改变任何事情,但是如果我更改视觉和颜色图,那么即使窗口深度不是 32,它也无法绘制任何东西。
  • 谢谢。我试过这样:hastebin.com/rowulorojo.rust;更改颜色图不会改变任何事情,但是如果我更改视觉和颜色图,那么即使窗口深度不是 32,它也无法绘制任何东西。如果我比较 XDefaultScreen 的返回值和我自定义构造的返回值,则正如预期的那样,唯一的区别是视觉ID。因此,使用视觉效果并不能解决问题,反而会使问题变得更糟。很有趣。
  • stackoverflow.com/questions/69693078/… 我尝试在框架上创建一个子窗口并让它渲染得很好。但是,如果我在 that 中绘制一些东西,它仍然无法在深度 32 窗口上工作(但 bg 呈现)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 2013-10-14
  • 2023-03-09
  • 2013-08-19
相关资源
最近更新 更多