xkb: simplify marshalling
The Xkb protocol is a complex beast, and so is it's current implementation. In order to clear the road for #1701 it needs to be untwisted, cleaned up and simplified.
Intentionally untwisting xkb in smaller, easily digestible steps, otherwise review would have become pretty hard.
Major points:
- simplifying call and data flow (eg. try not to pass around partially filled reply struct, instead the required values explicitl)
- reduce very short lived heap allocations by using stack (scoped fields) instead
- prefer struct initializers instead of piece-by-piece assignments
- split out cases where replies can also be contained in another one (xkbSend*(), ...)
- collect reply fragments in local buffers, so the complete reply can be written out at once.
Once this queue is merged, further simplifications become easy -- see #1701..
Also makes it easier for adding non-socket/stream based transports (binder, shmem, virtio, ...).