sawfish_client/
error.rs

1// sawfish-client -- client library to communicate with Sawfish window manager
2// © 2025 by Michał Nazarewicz <mina86@mina86.com>
3
4#[cfg(feature = "experimental-xcb")]
5use xcb::x;
6
7/// Error during establishing connection to the Sawfish server.
8#[derive(Debug, derive_more::From)]
9#[non_exhaustive]
10pub enum ConnError {
11    /// No display specified and DISPLAY environment variable not set.
12    NoDisplay,
13    /// LOGNAME environment variable not set.
14    ///
15    /// This is relevant when connecting to Unix socket since without the login
16    /// name socket name cannot be determined.
17    NoLogname,
18    /// An I/O error during establishing of the connection (e.g. Unix socket
19    /// does not exist or user lacks permissions to access it).
20    Io(std::path::PathBuf, std::io::Error),
21    /// Invalid X11 display screen number.
22    #[cfg(feature = "experimental-xcb")]
23    BadScreen(i32),
24    /// No Sawfish server found on display.
25    #[cfg(feature = "experimental-xcb")]
26    ServerNotFound,
27    /// An X11 error during establishing of the connection.
28    #[cfg(feature = "experimental-xcb")]
29    #[from(xcb::Error, xcb::ConnError, xcb::ProtocolError)]
30    X11(xcb::Error),
31}
32
33impl core::fmt::Display for ConnError {
34    fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
35        match self {
36            Self::NoDisplay => {
37                "No display specified and DISPLAY variable not set".fmt(fmtr)
38            }
39            Self::NoLogname => "LOGNAME environment variable not set".fmt(fmtr),
40            #[cfg(feature = "experimental-xcb")]
41            Self::BadScreen(screen) => {
42                write!(fmtr, "Invalid screen number {screen}")
43            }
44            #[cfg(feature = "experimental-xcb")]
45            Self::ServerNotFound => {
46                "No Sawfish server found on X11 screen".fmt(fmtr)
47            }
48            #[cfg(feature = "experimental-xcb")]
49            Self::X11(err) => err.fmt(fmtr),
50            Self::Io(path, err) => write!(fmtr, "{}: {}", path.display(), err),
51        }
52    }
53}
54
55
56/// Error during sending form for evaluation.
57#[derive(Debug, derive_more::From)]
58#[non_exhaustive]
59pub enum EvalError {
60    /// Got empty response to non-async request.
61    ///
62    /// Note that this is different than the response data being empty.  The
63    /// data, what [`crate::Client::eval`] returns in `Ok` variant, may be empty
64    /// and that’s not considered an error.
65    NoResponse,
66    /// Response too large to handle.  This can only happen on systems where
67    /// `usize` is smaller than 64-bit.
68    ResponseTooLarge(std::ffi::c_ulong),
69    /// An I/O error during communication with the Sawfish server.
70    #[from(std::io::Error, std::io::ErrorKind)]
71    Io(std::io::Error),
72    /// Invalid format of the window’s response property.
73    #[cfg(feature = "experimental-xcb")]
74    BadResponse {
75        /// The portal window where the response was read from.
76        window: x::Window,
77        /// The atom identifier of the property with the response.
78        atom: x::Atom,
79        /// The actual type of the response property (an atom), see
80        /// [`x::GetPropertyReply::type`].
81        typ: x::Atom,
82        /// The actual format of the response property, see
83        /// [`x::GetPropertyReply::format`].
84        format: u8,
85    },
86    /// X11 error during communication with Sawfish server.
87    #[cfg(feature = "experimental-xcb")]
88    #[from(xcb::Error, xcb::ConnError, xcb::ProtocolError)]
89    X11(xcb::Error),
90}
91
92impl core::fmt::Display for EvalError {
93    fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
94        match self {
95            Self::NoResponse => "No response to non-async request".fmt(fmtr),
96            Self::ResponseTooLarge(len) => {
97                write!(fmtr, "Response of {len} bytes too large")
98            }
99            Self::Io(err) => err.fmt(fmtr),
100            #[cfg(feature = "experimental-xcb")]
101            Self::BadResponse { window, atom, typ, format } => {
102                use xcb::Xid;
103                write!(
104                    fmtr,
105                    "Invalid format of response property (window:{}, atom:{}, \
106                     typ:{}, format:{})",
107                    window.resource_id(),
108                    atom.resource_id(),
109                    typ.resource_id(),
110                    format
111                )
112            }
113            #[cfg(feature = "experimental-xcb")]
114            Self::X11(err) => err.fmt(fmtr),
115        }
116    }
117}
118
119
120impl std::error::Error for ConnError {}
121impl std::error::Error for EvalError {}