Xcb

From KDE Community Wiki
Revision as of 21:45, 25 July 2012 by Fredrik (talk | contribs)

Introduction

Porting Xlib calls to xcb is fairly straightfoward, since most of the time it's a matter of replacing a call to an Xlib function with a call to the equivalent xcb function. This page mainly deals with exceptions to that rule, and things that might not be obvious even if you are familiar with Xlib.

Porting can be done gradually, since you can mix xcb and Xlib calls. The only exception is event processing. The event queue is managed either by xcb or Xlib, not both at the same time.

Macros

RootWindow(), DisplayWidth(), DisplayHeight(), DefaultDepth() etc.

Xlib code
    Window root = RootWindow(dpy, screen);
    int depth = DefaultDepth(dpy, screen);
    int width = DisplayWidth(dpy, screen);
    int height = DisplayHeight(dpy, screen);
xcb equivalent
    xcb_screen_t *screen = xcb_aux_get_screen(c, screen);
    xcb_window_t root = screen->root;
    int depth = screen->root_depth;
    int width = screen->width;
    int height = screen->height;


If you need a pointer to the xcb_screen_t for the default screen, call QPlatformNativeInterface::nativeResourceForWindow("screen", 0)) and cast the returned pointer to xcb_screen_t *.

DefaultRootWindow(), DefaultVisual(), DefaultDepth(), DefaultColormap()

See the previous section and the comment about obtaining a pointer to the xcb_screen_t for the default screen.

Functions

XSelectInput()

XSelectInput() is a convenience function that uses the ChangeWindowAttributes request to change the event mask for a window. The xcb equivalent of XSelectInput() is thus xcb_change_window_attributes().

Xlib example
XSelectInput(dpy, window, PropertyChangeMask);
xcb equivalent
uint32_t mask = XCB_EVENT_MASK_PROPERTY_CHANGE;
xcb_change_window_attributes(c, window, XCB_CW_EVENT_MASK, &mask);


Note that this applies only to XSelectInput(), not other input selection functions added by extensions.

XSync()

The xcb equivalent of XSync() is xcb_aux_sync(), which is in xcb-utils.

The reason you won't find a sync function in libxcb is that there is no sync request in the X protocol. Calling XSync() or xcb_aux_sync() is equivalent to calling XGetInputFocus() and throwing away the reply.

XMoveWindow(), XResizeWindow(), XMoveResizeWindow(), XSetWindowBorderWidth(), XRaiseWindow(), XLowerWindow(), XRestackWindows()

These functions are Xlib convenience functions that translate to the same X request; ConfigureWindow. The xcb equivalent is thus xcb_configure_window().

XMoveResize() example
    XMoveWindow(dpy, window, x, y);

    uint32_t values[] = { x, y };
    xcb_configure_window(c, window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
XRaiseWindow() example
    XRaiseWindow(dpy, window);

    uint32_t value = XCB_STACK_MODE_ABOVE;
    xcb_configure_window(c, window, XCB_CONFIG_STACK_MODE, &value);


Multiple calls to these functions can be combined into single call to xcb_configure_window():

    XMoveWindow(dpy, window, x, y);
    XResizeWindow(dpy, window, width, height);
    XRaiseWindow(dpy, window);

    uint32_t values[] = { x, y, width, height, XCB_STACK_MODE_ABOVE };
    xcb_configure_window(c, window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
                         XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_STACK_MODE,
                         values);


Note that the order of the values in the values array must match the order in the xcb_config_window_t enum.

Creating Resources

In this example we're going to look at how to create a pixmap in Xlib and in xcb, and look at the differences.

Xlib example
    Pixmap pixmap = XCreatePixmap(dpy, root, width, height, depth);
xcb equivalent
    xcb_pixmap_t pixmap = xcb_generate_id();
    xcb_create_pixmap(c, depth, pixmap, root, width, height);


XCreatePixmap() creates a pixmap with the specified width, height and depth, and returns a handle to the newly created pixmap.

In the xcb version we call xcb_generate_id() to create the pixmap handle, and then we pass the handle to the xcb_create_pixmap() function.

When a client connects to the X server it is given a range of unique global ID's that can be assigned to new resources. XCreatePixmap() picks the first unused ID in this range, and tells the X server to assign that ID to the pixmap when it creates it. After sending the request, XCreatePixmap() returns the ID to the caller.

Unlike Xlib, xcb doesn't hide these details from us. Whenever you create a new resource, you start by calling xcb_generate_id() to get an ID that can be assigned to the resource. The ID is always passed as a parameter to the function that creates the resource.

The advantage of this design is that creating resources is asynchronous, since the client doesn't have to wait for the X server to send back the ID after creating the resource. The disadvantage is that if resource creation fails for any reason, the ID will never become valid and we won't find out about it until later.

A different example that creates a region:

        xcb_rectangle_t rect = { 0, 0, 100, 100 };

        xcb_xfixes_region_t region = xcb_generate_id();
        xcb_xfixes_create_region(c, region, 1, &rect);