[英]How do I get the X window class given a window ID with rust-xcb?
I'm trying to use rust-xcb to get a window's class given a window ID. 我正在尝试使用rust-xcb获取给定窗口ID的窗口类。
fn get_class(conn: &xcb::Connection, id: &i32) {
let window: xcb::xproto::Window = *id as u32;
let class_prop: xcb::xproto::Atom = 67; // XCB_ATOM_WM_CLASS from xproto.h
let cookie = xcb::xproto::get_property(&conn, false, window, class_prop, 0, 0, 2);
match cookie.get_reply() {
Ok(reply) => {
let x: &[std::os::raw::c_void] = reply.value();
println!("reply is {:?}", x[0]);
}
Err(err) => println!("err {:?}", err),
}
}
The documentation is kind of sparse and hasn't been incredibly helpful, though I did find this bit about the GetPropertyReply
and of the xcb_get_property_reply_t
it wraps. 尽管我确实发现了有关
GetPropertyReply
和它包装的xcb_get_property_reply_t
一些知识,但是该文档还是比较稀疏的,并没有得到很大的帮助。
I looked at this answer in JavaScript but I don't know what the ctypes
equivalent in Rust is. 我用JavaScript看了这个答案,但是不知道Rust中的
ctypes
是什么。 I tried just casting the &[c_void]
as a &str
or String
: 我尝试将
&[c_void]
强制转换为&str
或String
:
...
Ok(reply) => {
let len = reply.value_len() as usize;
let buf = reply.value() as &str;
println!("{}", buf.slice_unchecked(0, len)); // this seems redundant
}
...
but it returns 但它返回
error: non-scalar cast: `&[_]` as `&str`
I tried casting the &[c_void]
as a &[u8]
and then collecting the Vec
into a String
, which sort of works: 我尝试将
&[c_void]
为&[u8]
,然后将Vec
收集到String
, &[c_void]
工作如下:
...
Ok(reply) => {
let value : &[u8] = reply.value();
let buf : String = value.into_iter().map(|i| *i as char).collect();
println!("\t{:?}", buf);
}
...
but I'm now getting weird results. 但是我现在得到的结果很奇怪。 for example , when I use
xprop
on Chrome I see "google-chrome" but for me it is only showing "google-c", and "roxterm" is showing up as "roxterm\\u{0}\u0026quot;. 例如,当我在Chrome上使用
xprop
,我看到“ google-chrome”,但对我来说它仅显示“ google-c”,而“ roxterm”则显示为“ roxterm \\ u {0}”。 I'm guessing "\\u{0}\u0026quot; is something Unicode related but I'm not sure, and I don't know why stuff is being concatenated either. 我猜“ \\ u {0}”与Unicode有关,但我不确定,我也不知道为什么东西也要串联起来。 Maybe I have to check the reply again?
也许我必须再次检查回复?
Here's my updated function: 这是我更新的功能:
fn get_class(conn: &Connection, id: &i32) -> String {
let window: xproto::Window = *id as u32;
let long_length: u32 = 8;
let mut long_offset: u32 = 0;
let mut buf = Vec::new();
loop {
let cookie = xproto::get_property(
&conn,
false,
window,
xproto::ATOM_WM_CLASS,
xproto::ATOM_STRING,
long_offset,
long_length,
);
match cookie.get_reply() {
Ok(reply) => {
let value: &[u8] = reply.value();
buf.extend_from_slice(value);
match reply.bytes_after() {
0 => break,
_ => {
let len = reply.value_len();
long_offset += len / 4;
}
}
}
Err(err) => {
println!("{:?}", err);
break;
}
}
}
let result = String::from_utf8(buf).unwrap();
let results: Vec<&str> = result.split('\0').collect();
results[0].to_string()
}
There were three main parts to this question: 这个问题包括三个主要部分:
xproto::get_property()
in a loop so I could check reply.bytes_after()
and accordingly adjust long_offset
. xproto::get_property()
放入循环中,以便可以检查reply.bytes_after()
并相应地调整long_offset
。 I think with an appropriate long_length
there will usually only be one read, but just being safe. long_length
通常只会读取一次,但只是安全起见。 &[u8] -> String
should be done using String::from_utf8
, which needs a Vec
; &[u8] -> String
应该使用String::from_utf8
,这需要一个Vec
; so I let mut buf = Vec::new()
and buf.extend_from_slice
over the loop before creating the result string with String::from_utf8(buf).unwrap()
String::from_utf8(buf).unwrap()
创建结果字符串之前, let mut buf = Vec::new()
和buf.extend_from_slice
遍历循环。 \\0
and grab the first value. \\0
并获取第一个值。 I might've just been looking in the wrong place, but xcb has absolutely terrible documentation.. 我可能一直在找错地方,但是xcb的文档绝对糟糕。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.