x11rb库create_window的x/y参数无法改变窗口位置的原因排查
X11rb中create_window的x/y参数不生效,但configure_window可调整位置的原因
我正在使用Rust的x11rb库与X11服务器交互,修改create_window中的width和height参数时窗口可正常调整大小,但修改其中的x和y参数无法改变窗口位置。不过使用configure_window却能成功调整窗口位置。运行环境为Ubuntu 22.10、X11及NVIDIA闭源驱动。
初始代码(x/y参数不生效):
use std::error::Error; use x11rb::connection::Connection; use x11rb::protocol::xproto::*; use x11rb::COPY_DEPTH_FROM_PARENT; fn main() -> Result<(), Box<dyn Error>> { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; // Ask for our window's Id let win = conn.generate_id()?; // Create the window conn.create_window( COPY_DEPTH_FROM_PARENT, // depth (same as root) win, // window Id screen.root, // parent window 200, // x 200, // y 150, // width 150, // height 10, // border width WindowClass::INPUT_OUTPUT, // class screen.root_visual, // visual &Default::default(), )?; // masks, not used yet // Map the window on the screen conn.map_window(win)?; // Make sure commands are sent before the sleep, so window is shown conn.flush()?; std::thread::sleep(std::time::Duration::from_secs(10)); Ok(()) }
有效的位置调整代码:
let values = ConfigureWindowAux::default().x(500).y(200); conn.configure_window(win, &values)?;
原因分析
- 窗口管理器的干预:X11中,顶层窗口(父窗口为根窗口)创建时指定的x/y位置通常会被窗口管理器忽略。窗口管理器会遵循自身的布局策略(比如平铺、浮动规则、用户预设位置)重新定位窗口,因此
create_window中的x/y参数会被覆盖。 - configure_window的特殊性:
configure_window是向窗口管理器发送的显式位置调整请求,窗口管理器一般会尊重这类指令(除非有强制布局限制),因此能成功调整窗口位置。
让create_window的x/y参数生效的方法
如果需要让create_window的x/y参数直接生效,可以通过以下方式:
- 创建非顶层窗口(以其他窗口为父窗口),此时窗口管理器不会干预其位置。
- 设置窗口的
override_redirect属性为true,让窗口管理器忽略该窗口。这样窗口会按照指定位置显示,但会失去窗口管理器提供的标题栏、边框、窗口控制按钮等功能。修改代码示例:
// 创建窗口时指定override_redirect属性 let attrs = CreateWindowAux::default().override_redirect(true); conn.create_window( COPY_DEPTH_FROM_PARENT, win, screen.root, 200, 200, 150, 150, 10, WindowClass::INPUT_OUTPUT, screen.root_visual, &attrs, )?;
内容的提问来源于stack exchange,提问作者wyc
相关产品推荐
相关产品推荐

