86 lines
3.1 KiB
Rust
86 lines
3.1 KiB
Rust
// This program shows error handling. It causes some X11 errors and shows where they end up.
|
|
//
|
|
// This program also serves as a (bad) integration test. To verify that the expected behaviour
|
|
// occurs, it needs to do some extra work. In particular, all calls to .sequence_number() are not
|
|
// needed for the example, but only for the test. Where needed, extra comments indicate how the
|
|
// short version of each case would look.
|
|
|
|
extern crate x11rb;
|
|
|
|
use x11rb::connection::Connection;
|
|
use x11rb::errors::ReplyError;
|
|
use x11rb::protocol::xproto::ConnectionExt as _;
|
|
use x11rb::protocol::Event;
|
|
use x11rb::wrapper::ConnectionExt as _;
|
|
|
|
const INVALID_WINDOW: u32 = 0;
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let (conn, _) = connect(None).unwrap();
|
|
|
|
// For requests with responses, there are four possibilities:
|
|
|
|
// We can just normally get the response or error to the request via reply()
|
|
let res = conn.get_geometry(INVALID_WINDOW)?.reply();
|
|
assert!(res.is_err());
|
|
|
|
// We can decide that we do not care about the response and also do not care about errors via
|
|
// discard_reply_and_errors()
|
|
conn.get_geometry(INVALID_WINDOW)?
|
|
.discard_reply_and_errors();
|
|
|
|
// Errors can show up as 'events' in wait_for_event() via reply_unchecked()
|
|
let cookie = conn.get_geometry(INVALID_WINDOW)?;
|
|
let seq1 = cookie.sequence_number();
|
|
let res = cookie.reply_unchecked()?;
|
|
assert!(res.is_none());
|
|
// The short version of the above would be:
|
|
// let res = conn.get_geomtry(INVALID_WINDOW)?.reply_unchecked()?;
|
|
|
|
// Errors can show up as 'events' in wait_for_event() by just dropping the cookie
|
|
let cookie = conn.get_geometry(INVALID_WINDOW)?;
|
|
let seq2 = cookie.sequence_number();
|
|
drop(cookie);
|
|
// The short version of the above would be:
|
|
// drop(conn.get_geometry(INVALID_WINDOW)?);
|
|
|
|
// For requests without responses, there are three possibilities
|
|
|
|
// We can check for errors explicitly
|
|
match conn.destroy_window(INVALID_WINDOW)?.check() {
|
|
Err(ReplyError::X11Error(_)) => {}
|
|
e => panic!("{e:?} unexpected"),
|
|
}
|
|
|
|
// We can silently ignore the error
|
|
conn.destroy_window(INVALID_WINDOW)?.ignore_error();
|
|
|
|
// An error can be handled as an event.
|
|
let cookie = conn.destroy_window(INVALID_WINDOW)?;
|
|
let seq3 = cookie.sequence_number();
|
|
drop(cookie);
|
|
// The short version of the above would be:
|
|
// drop(conn.destroy_window(INVALID_WINDOW)?);
|
|
|
|
// Synchronise with the server so that all errors are already received.
|
|
conn.sync()?;
|
|
|
|
// Now check if the things above really caused errors. This is the part that is supposed to
|
|
// turn this example into a (bad) integration test.
|
|
for &seq in &[seq1, seq2, seq3] {
|
|
let (event, seq2) = conn.wait_for_event_with_sequence()?;
|
|
match event {
|
|
Event::Error(_) => {}
|
|
event => panic!("Unexpectedly got {event:?} instead of an X11 error"),
|
|
}
|
|
assert_eq!(seq, seq2);
|
|
}
|
|
assert!(conn.poll_for_event()?.is_none());
|
|
|
|
println!("Done");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
include!("integration_test_util/connect.rs");
|