Expand description
Rust bindings to the XCB library.
The X protocol C-language Binding (XCB - https://xcb.freedesktop.org/) is a replacement for Xlib featuring a small footprint, latency hiding, direct access to the protocol, improved threading support, and extensibility.
The communication is established with the X server by the creation of a Connection object.
A client communicates with the server by sending requests. There are 2 types of requests:
- void requests: requests that do not expect an answer (e.g. x::ChangeProperty)
- non-void requests: requests that need a
Reply
(e.g. x::GetProperty)
Requests are passed to the server by filling a request structure e.g. x::CreateWindow and passing it to Connection::send_request.
The server can also communicate with clients by sending Event
s.
The client listens to events with calls such as Connection::wait_for_event
(blocking) or Connection::poll_for_event (non-blocking).
The x module contains definitions of the core X protocol. Each extension is defined in its own module such as xkb or render, and is activated by a cargo feature of the same name.
§Example
Here is a walk-through of a simple xcb
client.
// we import the necessary modules (only the core X module in this application).
use xcb::{x};
// we need to import the `Xid` trait for the `resource_id` call down there.
use xcb::{Xid};
// Many xcb functions return a `xcb::Result` or compatible result.
fn main() -> xcb::Result<()> {
// Connect to the X server.
let (conn, screen_num) = xcb::Connection::connect(None)?;
// Fetch the `x::Setup` and get the main `x::Screen` object.
let setup = conn.get_setup();
let screen = setup.roots().nth(screen_num as usize).unwrap();
// Generate an `Xid` for the client window.
// The type inference is needed here.
let window: x::Window = conn.generate_id();
// We can now create a window. For this we pass a `Request`
// object to the `send_request_checked` method. The method
// returns a cookie that will be used to check for success.
let cookie = conn.send_request_checked(&x::CreateWindow {
depth: x::COPY_FROM_PARENT as u8,
wid: window,
parent: screen.root(),
x: 0,
y: 0,
width: 150,
height: 150,
border_width: 0,
class: x::WindowClass::InputOutput,
visual: screen.root_visual(),
// this list must be in same order than `Cw` enum order
value_list: &[
x::Cw::BackPixel(screen.white_pixel()),
x::Cw::EventMask(x::EventMask::EXPOSURE | x::EventMask::KEY_PRESS)
],
});
// We now check if the window creation worked.
// A cookie can't be cloned; it is moved to the function.
conn.check_request(cookie)?;
// Let's change the window title
let cookie = conn.send_request_checked(&x::ChangeProperty {
mode: x::PropMode::Replace,
window,
property: x::ATOM_WM_NAME,
r#type: x::ATOM_STRING,
data: b"My XCB Window",
});
// And check for success again
conn.check_request(cookie)?;
// We now show ("map" in X terminology) the window.
// This time we do not check for success, so we discard the cookie.
conn.send_request(&x::MapWindow {
window,
});
// We need a few atoms for our application.
// We send a few requests in a row and wait for the replies after.
let (wm_protocols, wm_del_window, wm_state, wm_state_maxv, wm_state_maxh) = {
let cookies = (
conn.send_request(&x::InternAtom {
only_if_exists: true,
name: b"WM_PROTOCOLS",
}),
conn.send_request(&x::InternAtom {
only_if_exists: true,
name: b"WM_DELETE_WINDOW",
}),
conn.send_request(&x::InternAtom {
only_if_exists: true,
name: b"_NET_WM_STATE",
}),
conn.send_request(&x::InternAtom {
only_if_exists: true,
name: b"_NET_WM_STATE_MAXIMIZED_VERT",
}),
conn.send_request(&x::InternAtom {
only_if_exists: true,
name: b"_NET_WM_STATE_MAXIMIZED_HORZ",
}),
);
(
conn.wait_for_reply(cookies.0)?.atom(),
conn.wait_for_reply(cookies.1)?.atom(),
conn.wait_for_reply(cookies.2)?.atom(),
conn.wait_for_reply(cookies.3)?.atom(),
conn.wait_for_reply(cookies.4)?.atom(),
)
};
// We now activate the window close event by sending the following request.
// If we don't do this we can still close the window by clicking on the "x" button,
// but the event loop is notified through a connection shutdown error.
conn.check_request(conn.send_request_checked(&x::ChangeProperty {
mode: x::PropMode::Replace,
window,
property: wm_protocols,
r#type: x::ATOM_ATOM,
data: &[wm_del_window],
}))?;
// Previous request was checked, so a flush is not necessary in this case.
// Otherwise, here is how to perform a connection flush.
conn.flush()?;
let mut maximized = false;
// We enter the main event loop
loop {
match conn.wait_for_event()? {
xcb::Event::X(x::Event::KeyPress(ev)) => {
if ev.detail() == 0x3a {
// The M key was pressed
// (M only on qwerty keyboards. Keymap support is done
// with the `xkb` extension and the `xkbcommon-rs` crate)
// We toggle maximized state, for this we send a message
// by building a `x::ClientMessageEvent` with the proper
// atoms and send it to the server.
let data = x::ClientMessageData::Data32([
if maximized { 0 } else { 1 },
wm_state_maxv.resource_id(),
wm_state_maxh.resource_id(),
0,
0,
]);
let event = x::ClientMessageEvent::new(window, wm_state, data);
let cookie = conn.send_request_checked(&x::SendEvent {
propagate: false,
destination: x::SendEventDest::Window(screen.root()),
event_mask: x::EventMask::STRUCTURE_NOTIFY,
event: &event,
});
conn.check_request(cookie)?;
// Same as before, if we don't check for error, we have to flush
// the connection.
// conn.flush()?;
maximized = !maximized;
} else if ev.detail() == 0x18 {
// Q (on qwerty)
// We exit the event loop (and the program)
break Ok(());
}
}
xcb::Event::X(x::Event::ClientMessage(ev)) => {
// We have received a message from the server
if let x::ClientMessageData::Data32([atom, ..]) = ev.data() {
if atom == wm_del_window.resource_id() {
// The received atom is "WM_DELETE_WINDOW".
// We can check here if the user needs to save before
// exit, or in our case, exit right away.
break Ok(());
}
}
}
_ => {}
}
}
}
§Cargo features
The following Cargo features are available
§xlib_xcb
This feature activates the use of xlib::Display
to connect to XCB, therefore making
available both Xlib and XCB functions to the same connection.
While XCB is sufficient to handle all communication with the X server, some things can
still only be done by Xlib. E.g. hardware initialization for OpenGL is done by Xlib only.
§debug_atom_names
When this feature is activated, the fmt::Debug
implementation for x::Atom
will print
out the name of the atom in addition to its value.
E.g. the feature would turn Atom { res_id: 303 }
into Atom("Abs Pressure" ; 303)
.
This can be useful in situations where you are not sure which atom you have to intern in order to look up some data in a reply.
It should be noted that the feature sets global variable to have access to
the connection in the fmt::Debug
implementation, and that the Debug
print
have side effects (x::GetAtomName
requests) which can sometimes not be desirable.
The feature should therefore only be activated when needed.
§libxcb_v1_14
This feature is enabled by default and activates the libxcb API version 1.14. To use a version of the libxcb API prior to 1.14, you must disable it.
§Extension features
The following X extensions are activated by a cargo feature:
Extension name | Cargo feature |
---|---|
Composite | composite |
DAMAGE | damage |
DPMS | dpms |
DRI2 | dri2 |
DRI3 | dri3 |
Generic Event Extension | ge |
GLX | glx |
Present | present |
RANDR | randr |
RECORD | record |
RENDER | render |
X-Resource | res |
MIT-SCREEN-SAVER | screensaver |
SHAPE | shape |
MIT-SHM | shm |
SYNC | sync |
XEVIE | xevie |
XFree86-DRI | xf86dri |
XFree86-VidModeExtension | xf86vidmode |
XFIXES | xfixes |
XINERAMA | xinerama |
XInputExtension | xinput |
XKEYBOARD | xkb |
XpExtension | xprint |
SELinux | xselinux |
TEST | xtest |
XVideo | xv |
XVideo-MotionCompensation | xvmc |
Modules§
- The
BIG-REQUESTS
extension. - The
Composite
X extension. - The
DAMAGE
X extension. - The
DPMS
X extension. - The
DRI2
X extension. - The
DRI3
X extension. - Module for Foreign Function Interface bindings.
- The
Generic Event Extension
X extension. - The
GLX
X extension. - The
Present
X extension. - The
RANDR
X extension. - The
RECORD
X extension. - The
RENDER
X extension. - The
X-Resource
X extension. - The
MIT-SCREEN-SAVER
X extension. - The
SHAPE
X extension. - The
MIT-SHM
X extension. - The
SYNC
X extension. - The core X protocol definitions
- The
XC-MISC
extension. - The
XEVIE
X extension. - The
XFree86-DRI
X extension. - The
XFree86-VidModeExtension
X extension. - The
XFIXES
X extension. - The
XINERAMA
X extension. - The
XInputExtension
X extension. - The
XKEYBOARD
X extension. - The
XpExtension
X extension. - The
SELinux
X extension. - The
XTEST
X extension. - The
XVideo
X extension. - The
XVideo-MotionCompensation
X extension.
Macros§
- An helper macro that generate a struct of atoms.
Structs§
- Container for authentication information to connect to the X server
Connection
is the central object of XCB.- Display info returned by
parse_display
- Extension data as returned by each extensions
get_extension_data
. - A slice to a Latin-1 (aka. ISO 8859-1) string.
- Latin-1 (aka. ISO 8859-1) of fixed size
- A struct owning a Latin-1 (aka. ISO 8859-1) string.
- A struct that serve as an identifier for internal special queue in XCB
- SpecialEventIdDeprecatedA struct that serve as an identifier for internal special queue in XCB
- an event was not recognized as part of the core protocol or any enabled extension
- The default cookie type returned by void-requests.
- The checked cookie type returned by void-requests.
Enums§
- Error type that is returned by
Connection::has_error
. - The general error type for Rust-XCB.
- Unified Event type from the X server.
- Determines whether Xlib or XCB owns the event queue of
Connection
. - Refers to a X protocol extension.
- Error that can produce Latin-1 string operations
- A protocol error issued from the X server
Traits§
- A trait to designate base protocol errors.
- Trait for base events (aka. non GE_GENERIC events)
- General trait for cookies returned by requests.
- A marker trait for a cookie that allows synchronized error checking.
- A trait for checked cookies of requests that send a reply.
- A trait for unchecked cookies of requests that send a reply.
- A trait for GE_GENERIC events
- Trait for types that own a C allocated pointer and are represented by the data pointed to.
- Trait implemented by all requests to send the serialized data over the wire.
- Trait for request replies
- Trait implemented by requests types.
- Trait for requests that return a reply.
- Marker trait for requests that do not return a reply.
- A X resource trait
- Trait for X resources that can be created directly from
Connection::generate_id
Functions§
- Parses a display string in the form documented by X (7x).
Type Aliases§
- The result type associated with ConnError.
- The result type associated with ProtocolError.
- The general result type for Rust-XCB.