use x11rb::connection::Connection;
use x11rb::protocol::record::{self, ConnectionExt as _, Range8, ExtRange, CS};
use x11rb::protocol::xproto;
use x11rb::errors::ParseError;
use x11rb::x11_utils::TryParse;
fn print_reply_data(data: &[u8]) -> Result<(&[u8], bool), ParseError> {
match data[0] {
xproto::KEY_PRESS_EVENT => {
let (event, remaining) = xproto::KeyPressEvent::try_parse(data)?;
println!("key press: {:?}", event);
Ok((remaining, false))
}
xproto::KEY_RELEASE_EVENT => {
let (event, remaining) = xproto::KeyReleaseEvent::try_parse(data)?;
println!("key release: {:?}", event.detail);
Ok((remaining, event.detail == 9))
}
xproto::BUTTON_PRESS_EVENT => {
let (event, remaining) = xproto::ButtonPressEvent::try_parse(data)?;
println!("button press: {:?}", event);
Ok((remaining, false))
}
xproto::BUTTON_RELEASE_EVENT => {
let (event, remaining) = xproto::ButtonReleaseEvent::try_parse(data)?;
println!("button release: {:?}", event);
Ok((remaining, false))
}
xproto::MOTION_NOTIFY_EVENT => {
let (event, remaining) = xproto::MotionNotifyEvent::try_parse(data)?;
println!("motion notify: {:?}", event);
Ok((remaining, false))
}
0 => {
// This is a reply, we compute its length as follows
let (length, _) = u32::try_parse(&data[4..])?;
let length = usize::try_from(length).unwrap() * 4 + 32;
println!("unparsed reply: {:?}", &data[..length]);
Ok((&data[length..], false))
}
_ => {
// Error or event, they always have length 32
// TODO: What about XGE events?
println!("unparsed error/event: {:?}", &data[..32]);
Ok((&data[32..], false))
}
}
}
///
fn main() {
let (conn, screen_num) = x11rb::connect(None).unwrap();
let rc = conn.generate_id().unwrap();
let empty = Range8 { first: 0, last: 0 };
let empty_ext = ExtRange {
major: empty,
minor: record::Range16 { first: 0, last: 0 },
};
let range = record::Range {
core_requests: empty,
core_replies: empty,
ext_requests: empty_ext,
ext_replies: empty_ext,
delivered_events: empty,
device_events: Range8 {
// We want notification of core X11 events between key press and motion notify
first: xproto::KEY_PRESS_EVENT,
last: xproto::MOTION_NOTIFY_EVENT,
},
errors: empty,
client_started: false,
client_died: false,
};
let _ = conn.record_create_context(rc,
0,
&[CS::ALL_CLIENTS.into()],
&[range]);
for reply in conn.record_enable_context(rc).unwrap() {
match reply {
Ok(reply) => {
if reply.client_swapped {
println!("Byte swapped clients are unsupported");
} else if reply.category == 0 {
let mut remaining = &reply.data[..];
let mut should_exit = false;
while !remaining.is_empty() {
let (r, exit) = print_reply_data(&reply.data).unwrap();
remaining = r;
if exit {
should_exit = true;
}
}
if should_exit {
break;
}
} else if reply.category == 4 {
println!("Press Escape to exit...");
} else {
println!("Got a reply with an unsupported category: {:?}", reply);
}
}
Err(err) => {
println!("error:{}", err);
}
}
}
}