- Xlib
- Introducing XCB
- Remote Pointers and Errors
- Event Loops
- Events and Replies
- XCB Patterns
- Extensions
- Overall
Remote Pointers and Errors
When you create an object or structure on the local machine, you typically obtain a pointer to it. This is a unique identifier giving the address in memory of the object. When you create an object in some other address space, you need a more abstract representation.
Every object on the X server is identified by an XID. This is just an arbitrary number, and the X server internally maps it to something useful. Xlib lets you interact with XIDs almost as if they were pointers to opaque types. You get them as return values from functions.
This is one of the key areas where the XCB API has semantic differences to Xlib. There are two sorts of XID: those defined on the server and those defined on the client. If a resource is created in response to a server event, the server will assign an ID to it. If you are creating the resource, you need to create the ID yourself and then bind it to the resource as a two-step process. Consider how you create a window with the two APIs:
// XCB xcb_window_t winid = xcb_generate_id(connection); xcb_create_window(connection, depth, wid, parent, x, y, width, height, border_width, class, visual, value_mask, value_list); // Xlib Window xlibwinid = XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valuemask, attributes);
Both versions will complete immediately. In case of an error, the Xlib version will call one of two error callbacks. The XCB version handles errors a bit differently. The return value from xcb_create_window() is a cookie. All the asynchronous behavior in XCB is implemented via futures.
To get the real return value from any XCB function, you have two options. The simplest is to simply pass the cookie to another function, which gets the real return value. In this case, there is no real return. The cookie is an xcb_void_cookie_t, meaning a cookie which represents a “void” quantity in the future. You can pass this to xcb_request_check(), which will return an error if one occurred, or NULL if the request completed without error. This call will block until XCB receives a reply from the X server for this request.
The other alternative is to poll for replies. This allows you to register callbacks and handle the return values entirely asynchronously. This pair of approaches gives a lot of flexibility. Sometimes a bit of code needs the return value soon, and sometimes it only needs it at some arbitrary time in the future.