XCB Protocol Implementation Macro Language

by Jamey Sharp

Terminology

In this document, terms shall be used as follows.

A "field" is a unit of information in a real protocol request. Fields are never visible to programmers using XCB.

A "reply field" is a unit of information in a real protocol reply. Reply fields are directly visible to programmers using XCB.

A "param" ("parameter") is a unit of information passed to a protocol request wrapper function. It may or may not correspond to a field.

Responses

These macros desribe all data that comes from the X server.

Extension Support: BEGINEXTENSION and ENDEXTENSION

BEGINEXTENSION(X name, C name)
ENDEXTENSION

An extension's X name is the string used to identify it to the server (e.g. 'DPMS', 'SHAPE', 'XVideo'). The X protocol specification says that the X name of the extension "should use the ISO Latin-1 encoding, and uppercase and lowercase matter."

An extension's C name should be a valid C identifier which can be guessed easily from the X name: it will appear in some names visible to programmers using XCB.

VOIDREQUEST

VOIDREQUEST(name, 0 or more ?[#Request''Parameters''and Fields[PARAMs]])

Creates a function named [[XcbApi#XCBName][XCB<name>|XcbApi]] returning [[XcbApi#XCBNameCookie][XCBVoidCookie|XcbApi]] and accepting whatever parameters are necessary to deliver the given ?[#Request''Parameters''and Fields[PARAMs]] to the X server. Requests created with this macro do not expect a reply.

REQUEST

REQUEST(name, 0 or more ?[#Request''Parameters''and''Fields[PARAMs]], 1 or more ?[#Field''Declarations[FIELDs]])

Creates a function named [[XcbApi#XCBName][XCB<name>|XcbApi]] whose return result is an [[XcbApi#XCBNameCookie][XCB<name>Cookie|XcbApi]] and whose parameters are whatever is necessary to deliver the given ?[#Request''Parameters''and Fields[PARAMs]] to the X server. Declares the struct [[XcbApi#XCBNameCookie][XCB<name>Cookie|XcbApi]]. Creates a function named [[XcbApi#XCBNameReply][XCB<name>Reply|XcbApi]] returning a pointer to [[XcbApi#XCBNameRep][XCB<name>Rep|XcbApi]] which forces a cookie returned from [[XcbApi#XCBName][XCB<name>|XcbApi]], waiting for the response from the server if necessary. The ?[#Field Declarations[FIELDs]] must be quoted.

EVENT

EVENT(name, number, 1 or more FIELDs)

Declares the struct [[XcbApi#XCBEventNameEvent][XCB<name>Event|XcbApi]] containing the given FIELDs. Also defines [[XcbApi#XCBEventName][XCB<name>|XcbApi]] equal to number.

EVENTCOPY

EVENTCOPY(new name, new number, old name)

(undocumented)

ERROR

ERROR(name, number, 1 or more FIELDs)

Declares the struct [[XcbApi#XCBErrorNameError][XCB<name>Error|XcbApi]] containing the given FIELDs. Also defines [[XcbApi#XCBErrorName][XCB<name>|XcbApi]] equal to number.

ERRORCOPY

ERRORCOPY(new name, new number, old name)

(undocumented)

Request Parameters and Fields

These PARAM and FIELD macros may only appear within the second parameter to the ?[#REQUESTREQUEST] or ?[#VOIDREQUESTVOIDREQUEST] macros, and must always be quoted.

All of these macro calls must appear in the order specified by Appendix B (Protocol Encoding) of the X Window System Protocol specification, or the equivalent documentation for any extension. However, ?[#LISTPARAM[LISTs]] (including !LISTofVALUEs) are always grouped after any fixed-length section.

Information about padding bytes must be known, so you may need to specify it using the ?[#PADPAD] macro. However, in several cases this information can be inferred by the macros and thus can be omitted:

                 * After the last fixed-length field in a fixed-length request or reply. 
                 * After the last fixed-length field in a variable-length request. 
                 * Between each variable-length field and the next 4-byte aligned boundary in a request. 

OPCODE

OPCODE(number)

For extensions, this macro generates code to look up the major number and sets the minor number to the given value.

For the core protocol, this macro sets the major number to the given value.

PAD

PAD(bytes)

Inserts the given number of padding bytes.

PARAM

PARAM(type, name)

Defines a parameter with a field of the same type.

VALUEPARAM

VALUEPARAM(bitmask type, bitmask name, value array name)

Defines a BITMASK/LISTofVALUE parameter pair. The bitmask type should probably be either CARD16 or CARD32, depending on the specified width of the bitmask. The value array must be given to the generated function in the order the X server expects.

Caution! No type-, value-, or bounds-checking is done on this array by XCB. The X server and your operating system may not catch errors either, leading to odd results if you're not careful.

LISTPARAM

LISTPARAM(element type, list name, optional length expression)

Defines a !LISTofFOO parameter. The length of the list may be given as any C expression and may reference any of the other fields of this request.

If the length is not given, then it is obtained in a language-dependent manner. In C, a ?[#LOCALPARAMLOCALPARAM] is automatically generated for name_len immediately before the list parameter.

Note that requests like QueryTextExtents require a ?[#LOCALPARAMLOCALPARAM] for the length field, while others like InternAtom require a ?[#PARAMPARAM].

The recommended idiom for strings is to pass the length of the string into XCB, because it is much easier for callers to convert null-terminated strings to this style of counted strings than to go the other way around, and because requiring null-terminated strings as input could cause some valid protocol requests to be impossible to produce using XCB.

PARAM(CARD16, `name_len')
LISTPARAM(char, `name', `name_len')
_Example macro usage for strings with on-wire lengths._
LISTPARAM(char, `path')
_Example macro usage for strings without on-wire lengths._

LOCALPARAM

LOCALPARAM(type, name)

Defines a parameter with no associated field. The name can be used in expressions.

This macro can be useful in conjunction with LISTs where you need to pass the number of items to the ?[#LISTPARAMLISTPARAM] macro, but in the protocol the list length is implicit in the request length.

EXPRFIELD

EXPRFIELD(field name, expression)

Defines a field which should be filled in with the given expression. The field has no associated parameter. The name can be used in expressions.

This macro can be useful when the protocol requires an explicit field containing a value which is easily calculated from the information available.

In the core protocol, the only request that this is used for is QueryTextExtents, where the length of the string is implicit in the length of the request, with the exception that whether the string is odd or even length must be specified separately. This declaration expresses that:

EXPRFIELD(BOOL, `odd''length', `string''len & 1')

Historically, EXPRFIELD was also used to allow C-style null-terminated strings to be passed to XCB and converted to counted strings automatically. This usage is deprecated. See ?[#LISTPARAMLISTPARAM].

EXPRFIELD(CARD16, `name_len', `strlen(name)')
LISTPARAM(char, `name', `name_len')
_Deprecated example of converting a null-terminated string to a counted string._

ARRAYREPLY

ARRAYREPLY(field type, field name, length name)

Deprecated: use ?[#LISTFIELDLISTFIELD].

REPLY

REPLY(type, name)

Deprecated: use ?[#FIELDFIELD]

Utility Macros

Header File Generation

HEADERONLY and SOURCEONLY

These two macros are deprecated. They're too language-specific to appear in generics.xcb, and XCB should be able to figure out where to put all declarations on its own anyway.

Code which should appear only in a header (.h) file or only in an implementation (.c) file may be enclosed in the HEADERONLY and SOURCEONLY macros.

XCBGEN and ENDXCBGEN

XCBGEN(header name)
ENDXCBGEN()

The first line (aside from comments) of any XCB protocol implementation should contain a call to the XCBGEN macro, and the last line should contain a call to the ENDXCBGEN macro. The header name should generally be the base name of the source file, with all lowercase letters capitalized, and all other characters converted to underscores (""): for example, xcbconn.m4 uses XCB_CONN here.

XCBGEN automatically causes the header file to be #included by the implementation file.

Internal Macros

TOUPPER

TOUPPER(string)

Transliterates lowercase characters to uppercase.

UCFIRST

UCFIRST(string)

Transliterates the first character of the string to uppercase.

SPLIT

SPLIT(substring, string)

Split a string into a list of strings, at each point that the given substring appears.

JOIN

JOIN(sep, string, ...)

Join a list of strings with a given string as separator.

MAP

MAP(macro, string, ...)

Applies the macro to each following string and returns the transformed list.

UNIMPLEMENTED

(undocumented)

Diversions

PUSHDIV and divert should never be called with any number except -1. Instead, save the return value of ALLOCDIV into a macro that is named for the contents of the diversion, and use that macro.

define(`FUNCDIV', ALLOCDIV)
_Example of creating a new diversion._

Any use of divert(0) should be replaced with POPDIV(), and the first call to divert before that should be replaced with a call to PUSHDIV. This ensures that the protocol description file can be used in a wide variety of ways, including those that want only the values of the macros and diversions created inside the file.

ALLOCDIV

ALLOCDIV()

Returns a diversion number not currently in use.

PUSHDIV

PUSHDIV(diversion)

Pushes the given diversion onto the diversion stack, switching to it in the process.

POPDIV

POPDIV()

Pops the current diversion off the diversion stack, returning to the diversion which was in effect before the last ?[#PUSHDIVPUSHDIV].

Indentation

INDENT

INDENT()

Move line indentation to the right 4 spaces.

UNINDENT

UNINDENT()

Move line indentation to the left 4 spaces.

TAB

TAB()

Indent current line according to the current indentation level set by ?[#INDENTINDENT] and ?[#UNINDENTUNINDENT].

Functions

FUNCTION

FUNCTION(return type and function name, params, body)

Declares a C function, placing the appropriate prototype in the header file and the complete function in the implementation file.

STATICFUNCTION

STATICFUNCTION(return type and function name, params, body)

Declares a static-scope C function. No prototype is placed in the header file, and the keyword static is applied to the function in the implementation file.

INLINEFUNCTION

INLINEFUNCTION(return type and function name, params, body)

Declare a C function which should be compiled inline if possible. The function is placed in the header file and declared "static inline".

A future implementation of these macros should fall back to generating a regular function if inlines aren't supported by the compiler, but this isn't implemented yet.

Types

TYPEDEF

TYPEDEF(old name, new name)

(undocumented)

ENUM

ENUM(type name, name list)

(undocumented)

XIDTYPE

XIDTYPE(name)

Declares a struct holding an XID, and a function to allocate new instances of this struct.

STRUCT

STRUCT(name, 1 or more FIELDs)

Typedefs a structure defined to contain the given fields so that it has the given name.

UNION

UNION(name, 1 or more FIELDs)

Typedefs a union defined to contain the given fields so that it has the given name.

Field Declarations

These declarations may be used in ?[#STRUCTSTRUCT], ?[#UNIONUNION], or ?[#REQUESTREQUEST] reply definitions.

FIELD

FIELD(type, name)

Declares a field of the given type with the given name.

LISTFIELD

LISTFIELD(type, name, quantity)

Declares a list with the given name and containing the given quantity of elements of the given type.

If the given type is fixed-length, declares the [[XcbApi#XCBNameField][XCB<request><field>|XcbApi]] function.

If the given type has an iterator, declares the [[XcbApi#XCBNameFieldIter][XCB<request><field>Iter|XcbApi]] function.

Declares the [[XcbApi#XCBNameFieldLength][XCB<request><field>Length|XcbApi]] function.

ARRAYFIELD

ARRAYFIELD(type, name, quantity)

Deprecated: use ?[#LISTFIELDLISTFIELD].

Undocumented

These macros need to be documented.

COMMENT

(undocumented)