[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