[Xcb] XKB once again

Thomas Hunger hto at arcor.de
Fri Sep 7 11:16:13 PDT 2007


Hello again,

a short status update and API question for XKB:

Good news is that I can now read all XKB replies, including the ones 
which refer to other replies. Where "I can read" means I get the 
data, and it does not look completely bad.

The bad news: XKB has the funny idea of passing lists not at the end 
of a requests, but right in the middle. There is e.g. a 
CountedString8 which is used several times in a row in the 
request "ListComponents". CountedString8 is a struct:

    <struct name="KB_COUNTED_STRING8">
      <field type="CARD8" name="length" />
      <list type="char" name="string">
        <fieldref>length</fieldref>
      </list>
    </struct>

The server side code of ListCompoentens expects the following layout 
of the memory, where L is the length, and c any character of the 
string:

LccccLccccLccc...  (just an example for a list of CountedString8)

Now this kind of information needs to be packed into an iovec (namely 
one of the xcb_parts which get passed to send_request). Each iovec 
needs the pseudo-layout

    iov_base = "Lcccc"
    iov_len = len("Lcccc")

If this would only be necessary for CountedString8 I would just 
special case it. But there is also e.g. a list if KB_SHAPE which 
again contains a list of KB_OUTLINE, meaning KB_SHAPE needs to be 
packed in a pretty complicated way.

So after stating the situation here is the question: How should the 
user pass data into the request call? I could imagine to do it like 
this as a user:

    xcb_xkb_counted_string8_t*
    create_counted_string_8(uint8_t length, const char* string);

where xcb_xkb_counted_string8_t is the following struct.

    typedef struct xcb_xkb_kb_counted_string8_t {
        uint8_t length;
    } xcb_xkb_kb_counted_string8_t;

Now create_counted_string_8 would of course need to malloc an area big 
enough to store the bytes and copy them to the area. The helper 
function

   counted_string_8_size_in_bytes(xcb_xkb_kb_counted_string8_t* s);

which would be used to fill in the iov_len field of the iovec. Because 
we do a malloc we need to free the memory. The easiest solution would 
be if the request call takes ownership of the counted_string_8 and 
frees it after send_request.

In the same spirit it would be possible to pack more complex structs 
(psuedocode):

   xcb_xkb_kb_outline outlines[2];
   xcb_xkb_kb_point points[] = {{0, 0}, {1, 1}};
   outlines[0] = create_outline(2, 0, points) // 2 points
   outlines[1] = create_outline(2, 0, points) // 2 points
 
   // copy outlines to a linear piece of memory and free the mallocs
   // from create_outline:
   shape1 = create_shape(name, 2, 0, 0, outlines);
   shape2 = create_shape(name2, 2, 0, 0, outlines2);

   [...]

I know that all this is ugly, but all the XKB-calls are somewhat 
interdependant, so it seems to be "all or nothing".

Does anyone else have an opinion/ideas on this?

Tom


More information about the Xcb mailing list