This is a port of the C++ version of the XCB RandR reader.

I really, *really* like the way the Rust library is built and managed. It does a
really good job of emulating the XCB RandR macro found in KDE's Plasma and
libkscreen. The port was straightforward and my worries about memory management
were completely unfounded.
This commit is contained in:
Elf M. Sternberg 2022-04-15 19:52:53 -07:00
parent f821d87ba3
commit f60e935ffe
3 changed files with 119 additions and 0 deletions

3
xcb_read_rs/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
Cargo.lock
**/*.rs.bk
target

10
xcb_read_rs/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "xcb_read_rs"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libc = "0.2.102"
xcb = { version = "1.0.0-beta", features = ["randr"] }

106
xcb_read_rs/src/main.rs Normal file
View File

@ -0,0 +1,106 @@
extern crate libc;
extern crate xcb;
fn status_map(status: xcb::randr::SetConfig) -> &'static str {
match status {
xcb::randr::SetConfig::Success => "success",
xcb::randr::SetConfig::InvalidConfigTime => "invalid config time",
xcb::randr::SetConfig::InvalidTime => "invalid time",
xcb::randr::SetConfig::Failed => "failed",
}
}
fn rotation_map(rotation: xcb::randr::Rotation) -> &'static str {
match rotation {
xcb::randr::Rotation::ROTATE_0 => "normal",
xcb::randr::Rotation::ROTATE_90 => "portrait",
xcb::randr::Rotation::ROTATE_180 => "inverted",
xcb::randr::Rotation::ROTATE_270 => "portrait inverted",
_ => "unknown",
}
}
fn display_one_output(
conn: &xcb::Connection,
output: &xcb::randr::GetOutputInfoReply,
timestamp: xcb::x::Timestamp,
) {
let crtc = conn
.wait_for_reply(conn.send_request(&xcb::randr::GetCrtcInfo {
crtc: output.crtc(),
config_timestamp: timestamp,
}))
.unwrap();
println!(
"x: {}, y: {}, W×H: {}×{}, status: {}, rotation: {}",
crtc.x(),
crtc.y(),
crtc.width(),
crtc.height(),
status_map(crtc.status()),
rotation_map(crtc.rotation()),
)
}
fn display_outputs(
conn: &xcb::Connection,
screen: &xcb::randr::GetScreenResourcesReply,
timestamp: xcb::x::Timestamp,
) {
let output_cookies = screen
.outputs()
.iter()
.map(|output| {
conn.send_request(&xcb::randr::GetOutputInfo {
output: *output,
config_timestamp: timestamp,
})
})
.collect::<Vec<_>>();
for cookie in output_cookies.into_iter() {
let reply = conn.wait_for_reply(cookie).unwrap();
if reply.connection() == xcb::randr::Connection::Connected {
display_one_output(conn, &reply, timestamp)
}
}
}
fn get_screen_resources(
conn: &xcb::Connection,
root: &xcb::x::Window,
) -> xcb::randr::GetScreenResourcesReply {
conn.wait_for_reply(conn.send_request(&xcb::randr::GetScreenResources { window: *root }))
.unwrap()
}
fn display_xrandr_version(conn: &xcb::Connection) {
let randr_version = conn
.wait_for_reply(conn.send_request(&xcb::randr::QueryVersion {
major_version: xcb::randr::MAJOR_VERSION,
minor_version: xcb::randr::MINOR_VERSION,
}))
.unwrap();
println!(
"RandR Version {}.{}",
randr_version.major_version(),
randr_version.minor_version()
);
}
fn main() {
let (x_connection, screen_num) = xcb::Connection::connect(None).unwrap();
let setup = x_connection.get_setup();
let screen = setup.roots().nth(screen_num as usize).unwrap();
println!(
"{} x {}",
screen.width_in_pixels(),
screen.height_in_pixels()
);
display_xrandr_version(&x_connection);
let screen_resources = get_screen_resources(&x_connection, &screen.root());
let timestamp = screen_resources.config_timestamp();
display_outputs(&x_connection, &screen_resources, timestamp);
}