In this commit, we learned about X11 iterators, which iterate through

monstrous things allocated in memory that you just have to "know" are
of a certain structure.  In this case, we used `xcb_screen_next` to
say that we want the first (and all) screens attached to our current
X11 session.  And we used
`xcb_setup_roots_iterator(xcb_get_setup(connection))` to initialize
our iterator to our connection object in local memory.

Other things we've learned along the way: the file description that
represents our connection can be a TCP/IP socket or a Unix Domain
socket (a filesystem socket, named or not), and the only way to know
which is to find if there's a hostname before the colon ':' in the
display name of the server.  Not sure how that's going to work.

Also, found a really good reference: [Basic Graphics Tutorial with
XCB](https://www.x.org/releases/X11R7.6/doc/libxcb/tutorial/index.html).
It doesn't cover our specific use-case, but it's worth looking into.
This commit is contained in:
Elf M. Sternberg 2022-02-17 18:25:49 -08:00
parent 59a0c6acbf
commit bafa8bfd23
2 changed files with 61 additions and 3 deletions

53
docs/XCB_Cheatsheet.md Normal file
View File

@ -0,0 +1,53 @@
# XCB
XCB is a library for communicating with the X-Windows system used on
Linux, FreeBSD, and other Unix-like operating systems. XCB's interface
is written in C.
- Connecting, Verifying Connection, and Disconnecting the server.
-
## Connecting.
X-Windows is a server. It listens for events (keyboard events, mouse
events, timer events from connected programs, etc.) and "stores" the
results on a *display*, which is intended to be seen with the human
eye. A display is made up of one or more *screens*. Screens can be
literal (one of the physical devices in a multi-monitor setup) or
virtual (a virtualized desktop where the window manager supports
different "pages" on the same monitor), or even just parts of the same
physical screen space broken up by some logic.
To connect to X via XCB, you use the `xcb_connect` function. It takes two
arguments, a string with the name of the display, and a
pointer-to-int to the preferred screen. It returns an opaque data
structure, 'xcb_connection_t'.
```
xcb_connection_t* xcbConnection = xcb_connect(const char* display, int* screen);
```
There are variants for connection-with-authorization, and
connection-with-file-descriptor.
This function always returns an allocated structure, even on failure.
You _must_ test for failure with:
```
int error = xcb_connection_has_error(xcb_connection_t* xcbConnection);
```
The error is an number defined in `xcb.h`. See that file for the list
of possible failure modes.
## Disconnecting
You _must_ close the connection when you are finished. In the event
of a connection failure, you _must_ still call this function to
free the memory XCB used to report the connection failure:
```
void xcb_disconnect(xcb_connection_t* xcbConnection);
```

View File

@ -2,8 +2,13 @@
#include <xcb/xcb.h>
int main(int argc, const char *argv[]) {
xcb_connection_t *sXRandR11XCBConnection = xcb_connect(nullptr, nullptr);
std::cout << sXRandR11XCBConnection << std::endl;
xcb_disconnect(sXRandR11XCBConnection);
xcb_connection_t *xConnection = xcb_connect(nullptr, nullptr);
for (auto iter = xcb_setup_roots_iterator(xcb_get_setup(xConnection));
iter.rem; xcb_screen_next(&iter)) {
xcb_screen_t *screen = iter.data;
std::cout << "Screen " << iter.index << " (" << screen->width_in_pixels
<< ", " << screen->height_in_pixels << ")" << std::endl;
}
xcb_disconnect(xConnection);
return 0;
}