home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-30 | 57.2 KB | 2,008 lines |
- \&
- .sp 1
- .ce 3
- \s+1\fBAppendix C\fP\s-1
-
- \s+1\fBExtensions\fP\s-1
- .sp 2
- .na
- .LP
- .XS
- Appendix C: Extensions
- .XE
- Because X can evolve by extensions to the core protocol,
- it is important that extensions not be perceived as second class citizens.
- At some point,
- your favorite extensions may be adopted as additional parts of the
- X Standard.
- .LP
- Therefore, there should be little to distinguish the use of an extension from
- that of the core protocol.
- To avoid having to initialize extensions explicitly in application programs,
- it is also important that extensions perform ``lazy evaluations''
- and automatically initialize themselves when called for the first time.
- .LP
- This appendix describes techniques for writing extensions to Xlib that will
- run at essentially the same performance as the core protocol requests.
- .NT
- It is expected that a given extension to X consists of multiple
- requests.
- Defining ten new features as ten separate extensions is a bad practice.
- Rather, they should be packaged into a single extension
- and should use minor opcodes to distinguish the requests.
- .NE
- .LP
- The symbols and macros used for writing stubs to Xlib are listed in
- .IN "Files" "<X11/Xlibint.h>"
- .Pn < X11/Xlibint.h >.
- .SH
- Basic Protocol Support Routines
- .LP
- The basic protocol requests for extensions are
- .PN XQueryExtension
- and
- .PN XListExtensions .
- .IN "XQueryExtension" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- Bool XQueryExtension(\^\fIdisplay\fP, \fIname\fP, \fImajor_opcode_return\fP, \
- \fIfirst_event_return\fP, \fIfirst_error_return\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- char *\fIname;\fP\^
- .br
- int *\fImajor_opcode_return\fP\^;
- .br
- int *\fIfirst_event_return\fP\^;
- .br
- int *\fIfirst_error_return\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIname\fP 1i
- Specifies the extension name.
- .IP \fImajor_opcode_return\fP 1i
- Returns the major opcode.
- .IP \fIfirst_event_return\fP 1i
- Returns the first event code, if any.
- .IP \fI\fP 1i
- Specifies the extension list.
- .\" End marker code here
- .LP
- .PN XQueryExtension
- determines if the named extension is present.
- If the extension is not present,
- .PN False
- is returned;
- otherwise
- .PN True
- is returned.
- If the extension is present,
- the major opcode for the extension is returned to
- major_opcode_return;
- otherwise,
- zero is returned.
- Any minor opcode and the request formats are specific to the
- extension.
- If the extension involves additional event types,
- the base event type code is returned to first_event_return;
- otherwise,
- zero is returned.
- The format of the events is specific to the extension.
- If the extension involves additional error codes,
- the base error code is returned to first_error_return;
- otherwise,
- zero is returned.
- The format of additional data in the errors is specific to the extension.
- .LP
- If the extension name is not in the Host Portable Character Encoding
- the result is implementation dependent.
- Case matters; the strings \fIthing\fP, \fIThing\fP, and \fIthinG\fP
- are all considered different names.
- .IN "XListExtensions" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- char **XListExtensions(\^\fIdisplay\fP, \fInextensions_return\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int *\fInextensions_return\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fInextensions_return\fP 1i
- Returns the number of extensions listed.
- .\" End marker code here
- .LP
- .PN XListExtensions
- returns a list of all extensions supported by the server.
- If the data returned by the server is in the Latin Portable Character Encoding,
- then the returned strings are in the Host Portable Character Encoding.
- Otherwise, the result is implementation dependent.
- .IN "XFreeExtensionList" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- XFreeExtensionList(\^\fIlist\fP\^)
- .br
- char **\fIlist\fP\^;
- .FN
- .IP \fIlist\fP 1i
- Specifies the list of extension names.
- .\" End marker code here
- .LP
- .PN XFreeExtensionList
- frees the memory allocated by
- .PN XListExtensions .
- .SH
- Hooking into Xlib
- .LP
- These functions allow you to hook into the library.
- They are not normally used by application programmers but are used
- by people who need to extend the core X protocol and
- the X library interface.
- The functions, which generate protocol requests for X, are typically
- called stubs.
- .LP
- In extensions, stubs first should check to see if they have initialized
- themselves on a connection.
- If they have not, they then should call
- .PN XInitExtension
- to attempt to initialize themselves on the connection.
- .LP
- If the extension needs to be informed of GC/font allocation or
- deallocation or if the extension defines new event types,
- the functions described here allow the extension to be
- called when these events occur.
- .LP
- The
- .PN XExtCodes
- structure returns the information from
- .PN XInitExtension
- and is defined in
- .IN "Files" "<X11/Xlib.h>"
- .Pn < X11/Xlib.h >:
- .LP
- .IN "XExtCodes" "" "@DEF@"
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- typedef struct _XExtCodes { /* public to extension, cannot be changed */
- int extension; /* extension number */
- int major_opcode; /* major op-code assigned by server */
- int first_event; /* first event number for the extension */
- int first_error; /* first error number for the extension */
- } XExtCodes;
- .De
- .\" End marker code here
- .LP
- .IN "XInitExtension" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- XExtCodes *XInitExtension(\^\fIdisplay\fP, \fIname\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- char *\fIname\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIname\fP 1i
- Specifies the extension name.
- .\" End marker code here
- .LP
- .PN XInitExtension
- determines if the named extension exists.
- Then, it allocates storage for maintaining the
- information about the extension on the connection,
- chains this onto the extension list for the connection,
- and returns the information the stub implementor will need to access
- the extension.
- If the extension does not exist,
- .PN XInitExtension
- returns NULL.
- .LP
- If the extension name is not in the Host Portable Character Encoding
- the result is implementation dependent.
- Case matters; the strings \fIthing\fP, \fIThing\fP, and \fIthinG\fP
- are all considered different names.
- .LP
- The extension number in the
- .PN XExtCodes
- structure is
- needed in the other calls that follow.
- This extension number is unique only to a single connection.
- .LP
- .IN "XAddExtension" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- XExtCodes *XAddExtension\^(\^\fIdisplay\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .\" End marker code here
- .LP
- For local Xlib extensions,
- .PN XAddExtension
- allocates the
- .PN XExtCodes
- structure, bumps the extension number count,
- and chains the extension onto the extension list.
- (This permits extensions to Xlib without requiring server extensions.)
- .SH
- Hooks into the Library
- .LP
- These functions allow you to define procedures that are to be
- called when various circumstances occur.
- The procedures include the creation of a new GC for a connection,
- the copying of a GC, the freeing of a GC, the creating and freeing of fonts,
- the conversion of events defined by extensions to and from wire
- format, and the handling of errors.
- .LP
- All of these functions return the previous routine defined for this
- extension.
- .IN "XESetCloseDisplay" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetCloseDisplay(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when the display is closed.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called whenever
- .PN XCloseDisplay
- is called.
- This procedure returns any previously defined procedure, usually NULL.
- .LP
- When
- .PN XCloseDisplay
- is called,
- your routine is called
- with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIcodes\fP\^)
- Display *\fIdisplay\fP\^;
- XExtCodes *\fIcodes\fP\^;
- .De
- .\" End marker code here
- .LP
- .IN "XESetCreateGC" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetCreateGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when a GC is closed.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called whenever
- a new GC is created.
- This procedure returns any previously defined procedure, usually NULL.
- .LP
- When a GC is created,
- your routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIgc\fP, \fIcodes\fP\^)
- Display *\fIdisplay\fP\^;
- GC \fIgc\fP\^;
- XExtCodes *\fIcodes\fP\^;
- .De
- .\" End marker code here
- .LP
- .IN "XESetCopyGC" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetCopyGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when GC components are copied.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called whenever
- a GC is copied.
- This procedure returns any previously defined procedure, usually NULL.
- .LP
- When a GC is copied,
- your routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIgc\fP, \fIcodes\fP\^)
- Display *\fIdisplay\fP\^;
- GC \fIgc\fP\^;
- XExtCodes *\fIcodes\fP\^;
- .De
- .\" End marker code here
- .LP
- .IN "XESetFreeGC" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetFreeGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc)\fP\^)(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when a GC is freed.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called whenever
- a GC is freed.
- This procedure returns any previously defined procedure, usually NULL.
- .LP
- When a GC is freed,
- your routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIgc\fP, \fIcodes\fP\^)
- Display *\fIdisplay\fP\^;
- GC \fIgc\fP\^;
- XExtCodes *\fIcodes\fP\^;
- .De
- .\" End marker code here
- .LP
- .IN "XESetCreateFont" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetCreateFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when a font is created.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called whenever
- .PN XLoadQueryFont
- and
- .PN XQueryFont
- are called.
- This procedure returns any previously defined procedure, usually NULL.
- .LP
- When
- .PN XLoadQueryFont
- or
- .PN XQueryFont
- is called,
- your routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIfs\fP, \fIcodes\fP\^)
- Display *\fIdisplay\fP\^;
- XFontStruct *\fIfs\fP\^;
- XExtCodes *\fIcodes\fP\^;
- .De
- .\" End marker code here
- .LP
- .IN "XESetFreeFont" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetFreeFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int (\^*\fIproc\fP)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when a font is freed.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called whenever
- .PN XFreeFont
- is called.
- This procedure returns any previously defined procedure, usually NULL.
- .LP
- When
- .PN XFreeFont
- is called, your routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIfs\fP, \fIcodes\fP\^)
- Display *\fIdisplay\fP\^;
- XFontStruct *\fIfs\fP\^;
- XExtCodes *\fIcodes\fP\^;
- .De
- .\" End marker code here
- .LP
- The next two functions allow you to define new events to the library.
- An
- .PN XEvent
- structure always has a type code (type int) as the first component. This
- uniquely identifies what kind of event it is. The second component is
- always the serial number (type unsigned long) of the last request processed
- by the server. The third component is always a boolean (type Bool) indicating
- whether the event came from a
- .PN SendEvent
- protocol request. The fourth component is always a pointer to the display
- the event was read from. The fifth component is always a resource ID of
- one kind or another, usually a window, carefully selected to be useful to
- toolkit dispatchers. The fifth component should always exist, even if
- the event does not have a natural ``destination''; if there is no value
- from the protocol to put in this component, initialize it to zero.
- .NT
- There is an implementation limit such that your host event
- structure size cannot be bigger than the size of the
- .PN XEvent
- union of structures.
- There also is no way to guarantee that more than 24 elements or 96 characters
- in the structure will be fully portable between machines.
- .NE
- .IN "XESetWireToEvent" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetWireToEvent(\^\fIdisplay\fP, \fIevent_number\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIevent_number\fP\^;
- .br
- Status (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIevent_number\fP 1i
- Specifies the event code.
- .IP \fIproc\fP 1i
- Specifies the routine to call when converting an event.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called when an event
- needs to be converted from wire format
- .Pn ( xEvent )
- to host format
- .Pn ( XEvent ).
- The event number defines which protocol event number to install a
- conversion routine for.
- This procedure returns any previously defined procedure.
- .NT
- You can replace a core event conversion routine with one
- of your own, although this is not encouraged.
- It would, however, allow you to intercept a core event
- and modify it before being placed in the queue or otherwise examined.
- .NE
- When Xlib needs to convert an event from wire format to host
- format, your routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- Status (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIre\fP, \fIevent\fP\^)
- Display *\fIdisplay\fP\^;
- XEvent *\fIre\fP\^;
- xEvent *\fIevent\fP\^;
- .De
- .\" End marker code here
- .LP
- Your routine must return status to indicate if the conversion succeeded.
- The re argument is a pointer to where the host format event should be stored,
- and the event argument is the 32-byte wire event structure.
- In the
- .PN XEvent
- structure you are creating,
- you must fill in the five required members of the event structure.
- You should fill in the type member with the type specified for the
- .PN xEvent
- structure.
- You should copy all other members from the
- .PN xEvent
- structure (wire format) to the
- .PN XEvent
- structure (host format).
- Your conversion routine should return
- .PN True
- if the event should be placed in the queue or
- .PN False
- if it should not be placed in the queue.
- .LP
- To initialize the serial number component of the event, call
- .PN _XSetLastRequestRead
- with the event and use the return value.
- .LP
- .IN "_XSetLastRequestRead" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- unsigned long _XSetLastRequestRead(\^\fIdisplay\fP, \fIrep\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- xGenericReply *\fIrep\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIrep\fP 1i
- Specifies the wire event structure.
- .\" End marker code here
- .LP
- This function computes and returns a complete serial number from the partial
- serial number in the event.
- .sp
- .LP
- .IN "XESetEventToWire" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- Status (*XESetEventToWire(\^\fIdisplay\fP, \fIevent_number\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIevent_number\fP\^;
- .br
- int (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIevent_number\fP 1i
- Specifies the event code.
- .IP \fIproc\fP 1i
- Specifies the routine to call when converting an event.
- .\" End marker code here
- .LP
- You use this procedure to define a procedure to be called when an event
- needs to be converted from host format
- .Pn ( XEvent )
- to wire format
- .Pn ( xEvent )
- form.
- The event number defines which protocol event number to install a
- conversion routine for.
- This procedure returns any previously defined procedure.
- It returns zero if the conversion fails or nonzero otherwise.
- .NT
- You can replace a core event conversion routine with one
- of your own, although this is not encouraged.
- It would, however, allow you to intercept a core event
- and modify it before being sent to another client.
- .NE
- When Xlib needs to convert an event from host format to wire format,
- your routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIre\fP, \fIevent\fP\^)
- Display *\fIdisplay\fP\^;
- XEvent *\fIre\fP\^;
- xEvent *\fIevent\fP\^;
- .De
- .\" End marker code here
- .LP
- The re argument is a pointer to the host format event,
- and the event argument is a pointer to where the 32-byte wire event
- structure should be stored.
- You should fill in the type with the type from the
- .PN XEvent
- structure.
- All other members then should be copied from the host format to the
- .PN xEvent
- structure.
- .IN "XESetWireToError" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- Bool (*XESetWireToError(\^\fIdisplay\fP, \fIerror_number\fP, \fIproc\fP\^)(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIerror_number\fP\^;
- .br
- Bool (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIerror_number\fP 1i
- Specifies the error code.
- .IP \fIproc\fP 1i
- Specifies the routine to call when an error is received.
- .\" End marker code here
- .LP
- This function defines a procedure to be called when an extension
- error needs to be converted from wire format to host format.
- The error number defines which protocol error code to install
- the conversion routine for.
- This procedure returns any previously defined procedure.
- .LP
- Use this function for extension errors that contain additional error values
- beyond those in a core X error, when multiple wire errors must be combined
- into a single Xlib error, or when it is necessary to intercept an
- X error before it is otherwise examined.
- .LP
- When Xlib needs to convert an error from wire format to host format, the
- routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- Bool (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIhe\fP, \fIwe\fP\^)
- Display *\fIdisplay\fP\^;
- XErrorEvent *\fIhe\fP\^;
- xError *\fIwe\fP\^;
- .De
- .\" End marker code here
- .LP
- The he argument is a pointer to where the host format error should be stored.
- The structure pointed at by he is guaranteed to be as large as an
- .PN XEvent
- structure, and so can be cast to a type larger than an
- .PN XErrorEvent ,
- in order to store additional values.
- If the error is to be completely ignored by Xlib
- (for example, several protocol error structures will be combined into
- one Xlib error),
- then the function should return
- .PN False ;
- otherwise it should return
- .PN True .
- .IN "XESetError" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetError(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when an error is received.
- .\" End marker code here
- .LP
- Inside Xlib, there are times that you may want to suppress the
- calling of the external error handling when an error occurs.
- This allows status to be returned on a call at the cost of the call
- being synchronous (though most such routines are query operations, in any
- case, and are typically programmed to be synchronous).
- .LP
- When Xlib detects a protocol error in
- .PN _XReply ,
- it calls your procedure with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- int (*\fIproc\fP\^)(\fIdisplay\fP, \fIerr\fP, \fIcodes\fP, \fIret_code\fP\^)
- Display *\fIdisplay\fP\^;
- xError *\fIerr\fP\^;
- XExtCodes *\fIcodes\fP\^;
- int *\fIret_code\fP\^;
- .De
- .\" End marker code here
- .LP
- The err argument is a pointer to the 32-byte wire format error.
- The codes argument is a pointer to the extension codes structure.
- The ret_code argument is the return code you may want
- .PN _XReply
- returned to.
- .LP
- If your routine returns a zero value,
- the error is not suppressed, and
- the client's error handler is called.
- (For further information, see section 11.8.2.)
- If your routine returns nonzero,
- the error is suppressed, and
- .PN _XReply
- returns the value of ret_code.
- .IN "XESetErrorString" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- char *(*XESetErrorString(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- char *(\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call to obtain an error string.
- .\" End marker code here
- .LP
- The
- .PN XGetErrorText
- function returns a string to the user for an error.
- .PN XESetErrorString
- allows you to define a routine to be called that
- should return a pointer to the error message.
- The following is an example.
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIcode\fP, \fIcodes\fP, \fIbuffer\fP, \fInbytes\fP\^)
- Display *\fIdisplay\fP\^;
- int \fIcode\fP\^;
- XExtCodes *\fIcodes\fP\^;
- char *\fIbuffer\fP\^;
- int \fInbytes\fP\^;
- .De
- .\" End marker code here
- .LP
- Your procedure is called with the error code for every error detected.
- You should copy nbytes of a null-terminated string containing the
- error message into buffer.
- .IN "XESetPrintErrorValues" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- void (*XESetPrintErrorValues(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- void (\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when an error is printed.
- .\" End marker code here
- .LP
- This function defines a procedure to be called when an extension
- error is printed, to print the error values. Use this function for extension
- errors that contain additional error values beyond those in a core X error.
- This function returns any previously defined procedure.
- .LP
- When Xlib needs to print an error, the routine is called with these arguments:
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- .R
- void (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIev\fP, \fIfp\fP\^)
- Display *\fIdisplay\fP\^;
- XErrorEvent *\fIev\fP\^;
- void *\fIfp\fP\^;
- .De
- .\" End marker code here
- .LP
- The structure pointed at by ev is guaranteed to be as large as an
- .PN XEvent
- structure, and so can be cast to a type larger than an
- .PN XErrorEvent ,
- in order to obtain additional values set by using
- .PN XESetWireToError .
- The underlying type of the fp argument is system dependent;
- on a POSIX-compliant fp should be cast to type FILE*.
- .IN "XESetFlushGC" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- int (*XESetFlushGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- int \fIextension\fP\^;
- .br
- int *(\^*\fIproc\fP\^)(\^);
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIextension\fP 1i
- Specifies the extension number.
- .IP \fIproc\fP 1i
- Specifies the routine to call when a GC is flushed.
- .\" End marker code here
- .LP
- The
- .PN XESetFlushGC
- procedure is identical to
- .PN XESetCopyGC
- except that
- .PN XESetFlushGC
- is called when a GC cache needs to be updated in the server.
- .SH
- Hooks onto Xlib Data Structures
- .LP
- Various Xlib data structures have provisions for extension routines
- to chain extension supplied data onto a list.
- These structures are
- .PN GC ,
- .PN Visual ,
- .PN Screen ,
- .PN ScreenFormat ,
- .PN Display ,
- and
- .PN XFontStruct .
- Because the list pointer is always the first member in the structure,
- a single set of routines can be used to manipulate the data
- on these lists.
- .LP
- The following structure is used in the routines in this section
- and is defined in
- .IN "Files" "<X11/Xlib.h>"
- .Pn < X11/Xlib.h >:
- .LP
- .IN "XExtData" "" "@DEF@"
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- typedef struct _XExtData {
- int number; /* number returned by XInitExtension */
- struct _XExtData *next; /* next item on list of data for structure */
- int (*free_private)(); /* if defined, called to free private */
- XPointer private_data; /* data private to this extension. */
- } XExtData;
- .De
- .\" End marker code here
- .LP
- When any of the data structures listed above are freed,
- the list is walked, and the structure's free routine (if any) is called.
- If free is NULL,
- then the library frees both the data pointed to by the private_data member
- and the structure itself.
- .LP
- .\" Start marker code here
- .Ds 0
- .TA .5i
- .ta .5i
- union { Display *display;
- GC gc;
- Visual *visual;
- Screen *screen;
- ScreenFormat *pixmap_format;
- XFontStruct *font } XEDataObject;
- .De
- .\" End marker code here
- .LP
- .IN "XEHeadOfExtensionList" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- XExtData **XEHeadOfExtensionList(object)
- XEDataObject object;
- .FN
- .IP \fIobject\fP 1i
- Specifies the object.
- .\" End marker code here
- .LP
- .PN XEHeadOfExtensionList
- returns a pointer to the list of extension structures attached to the
- specified object.
- In concert with
- .PN XAddToExtensionList ,
- .PN XEHeadOfExtensionList
- allows an extension to attach arbitrary data to any of the structures
- of types contained in
- .PN XEDataObject .
- .LP
- .IN "XAddToExtensionList" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- XAddToExtensionList(\^\fIstructure\fP, \fIext_data\fP\^)
- .br
- XExtData **\fIstructure\fP\^;
- .br
- XExtData *\fIext_data\fP\^;
- .FN
- .IP \fIstructure\fP 1i
- Specifies the extension list.
- .IP \fIext_data\fP 1i
- Specifies the extension data structure to add.
- .\" End marker code here
- .LP
- The structure argument is a pointer to one of the data structures enumerated above.
- You must initialize ext_data->number with the extension number
- before calling this routine.
- .IN "XFindOnExtensionList" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- XExtData *XFindOnExtensionList(\^\fIstructure\fP, \fInumber\fP\^)
- .br
- struct _XExtData **\fIstructure\fP\^;
- .br
- int \fInumber\fP\^;
- .FN
- .IP \fIstructure\fP 1i
- Specifies the extension list.
- .IP \fInumber\fP 1i
- Specifies the extension number from XInitExtension.
- .\" End marker code here
- .LP
- .PN XFindOnExtensionList
- returns the first extension data structure for the extension numbered
- number.
- It is expected that an extension will add at most one extension
- data structure to any single data structure's extension data list.
- There is no way to find additional structures.
- .LP
- The
- .PN XAllocID
- macro, which allocates and returns a resource ID, is defined in
- .IN "Files" "<X11/Xlib.h>"
- .Pn < X11/Xlib.h >.
- .IN "XAllocID" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- XAllocID\^(\fIdisplay\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .\" End marker code here
- .LP
- This macro is a call through the
- .PN Display
- structure to the internal resource ID allocator.
- It returns a resource ID that you can use when creating new resources.
- .SH
- GC Caching
- .LP
- GCs are cached by the library to allow merging of independent change
- requests to the same GC into single protocol requests.
- This is typically called a write-back cache.
- Any extension routine whose behavior depends on the contents of a GC must flush
- the GC cache to make sure the server has up-to-date contents in its GC.
- .LP
- The
- .PN FlushGC
- macro checks the dirty bits in the library's GC structure and calls
- .PN _XFlushGCCache
- if any elements have changed.
- The
- .PN FlushGC
- macro is defined as follows:
- .IN "FlushGC" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- FlushGC\^(\^\fIdisplay\fP\^, \fIgc\fP\^)
- .br
- Display *\^\fIdisplay\fP\^;
- .br
- GC \fIgc\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .\" $Header: gc.a,v 1.2 88/05/09 11:20:34 mento Exp $
- .IP \fIgc\fP 1i
- Specifies the GC.
- .\" End marker code here
- .LP
- Note that if you extend the GC to add additional resource ID components,
- you should ensure that the library stub sends the change request immediately.
- This is because a client can free a resource immediately after
- using it, so if you only stored the value in the cache without
- forcing a protocol request, the resource might be destroyed before being
- set into the GC.
- You can use the
- .PN _XFlushGCCache
- procedure
- to force the cache to be flushed.
- The
- .PN _XFlushGCCache
- procedure
- is defined as follows:
- .IN "_XFlushGCCache" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- _XFlushGCCache\^(\^\fIdisplay\fP\^, \fIgc\fP\^)
- .br
- Display *\^\fIdisplay\fP\^;
- .br
- GC \fIgc\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .\" $Header: gc.a,v 1.2 88/05/09 11:20:34 mento Exp $
- .IP \fIgc\fP 1i
- Specifies the GC.
- .\" End marker code here
- .SH
- Graphics Batching
- .LP
- If you extend X to add more poly graphics primitives, you may be able to
- take advantage of facilities in the library to allow back-to-back
- single calls to be transformed into poly requests.
- This may dramatically improve performance of programs that are not
- written using poly requests.
- A pointer to an
- .PN xReq ,
- called last_req in the display structure, is the last request being processed.
- By checking that the last request
- type, drawable, gc, and other options are the same as the new one
- and that there is enough space left in the buffer, you may be able
- to just extend the previous graphics request by extending the length
- field of the request and appending the data to the buffer.
- This can improve performance by five times or more in naive programs.
- For example, here is the source for the
- .PN XDrawPoint
- stub.
- (Writing extension stubs is discussed in the next section.)
- .IP
- .\" Start marker code here
- .nf
- #include "copyright.h"
-
- #include "Xlibint.h"
-
- /* precompute the maximum size of batching request allowed */
-
- static int size = sizeof(xPolyPointReq) + EPERBATCH * sizeof(xPoint);
-
- XDrawPoint(dpy, d, gc, x, y)
- register Display *dpy;
- Drawable d;
- GC gc;
- int x, y; /* INT16 */
- {
- xPoint *point;
- LockDisplay(dpy);
- FlushGC(dpy, gc);
- {
- register xPolyPointReq *req = (xPolyPointReq *) dpy->last_req;
- /* if same as previous request, with same drawable, batch requests */
- if (
- (req->reqType == X_PolyPoint)
- && (req->drawable == d)
- && (req->gc == gc->gid)
- && (req->coordMode == CoordModeOrigin)
- && ((dpy->bufptr + sizeof (xPoint)) <= dpy->bufmax)
- && (((char *)dpy->bufptr - (char *)req) < size) ) {
- point = (xPoint *) dpy->bufptr;
- req->length += sizeof (xPoint) >> 2;
- dpy->bufptr += sizeof (xPoint);
- }
-
- else {
- GetReqExtra(PolyPoint, 4, req); /* 1 point = 4 bytes */
- req->drawable = d;
- req->gc = gc->gid;
- req->coordMode = CoordModeOrigin;
- point = (xPoint *) (req + 1);
- }
- point->x = x;
- point->y = y;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- }
- .fi
- .\" End marker code here
- .LP
- To keep clients from generating very long requests that may monopolize the
- server,
- there is a symbol defined in
- .IN "Files" "<X11/Xlibint.h>"
- .Pn < X11/Xlibint.h >
- of EPERBATCH on the number of requests batched.
- Most of the performance benefit occurs in the first few merged requests.
- Note that
- .PN FlushGC
- is called \fIbefore\fP picking up the value of last_req,
- because it may modify this field.
- .SH
- Writing Extension Stubs
- .LP
- All X requests always contain the length of the request,
- expressed as a 16-bit quantity of 32 bits.
- This means that a single request can be no more than 256K bytes in
- length.
- Some servers may not support single requests of such a length.
- The value of dpy->max_request_size contains the maximum length as
- defined by the server implementation.
- For further information,
- see ``X Window System Protocol.''
- .SH
- Requests, Replies, and Xproto.h
- .LP
- The
- .IN "Files" "<X11/Xproto.h>"
- .Pn < X11/Xproto.h >
- file contains three sets of definitions that
- are of interest to the stub implementor:
- request names, request structures, and reply structures.
- .LP
- You need to generate a file equivalent to
- .IN "Files" "<X11/Xproto.h>"
- .Pn < X11/Xproto.h >
- for your extension and need to include it in your stub routine.
- Each stub routine also must include
- .IN "Files" "<X11/Xlibint.h>"
- .Pn < X11/Xlibint.h >.
- .LP
- The identifiers are deliberately chosen in such a way that, if the
- request is called X_DoSomething, then its request structure is
- xDoSomethingReq, and its reply is xDoSomethingReply.
- The GetReq family of macros, defined in
- .IN "Files" "<X11/Xlibint.h>"
- .Pn < X11/Xlibint.h >,
- takes advantage of this naming scheme.
- .LP
- For each X request,
- there is a definition in
- .IN "Files" "<X11/Xproto.h>"
- .Pn < X11/Xproto.h >
- that looks similar to this:
- .LP
- .Ds
- .R
- #define X_DoSomething 42
- .De
- In your extension header file,
- this will be a minor opcode,
- instead of a major opcode.
- .SH
- Request Format
- .LP
- Every request contains an 8-bit major opcode and a 16-bit length field
- expressed in units of four bytes.
- Every request consists of four bytes of header
- (containing the major opcode, the length field, and a data byte) followed by
- zero or more additional bytes of data.
- The length field defines the total length of the request, including the header.
- The length field in a request must equal the minimum length required to contain
- the request.
- If the specified length is smaller or larger than the required length,
- the server should generate a
- .PN BadLength
- error.
- Unused bytes in a request are not required to be zero.
- Extensions should be designed in such a way that long protocol requests
- can be split up into smaller requests,
- if it is possible to exceed the maximum request size of the server.
- The protocol guarantees the maximum request size to be no smaller than
- 4096 units (16384 bytes).
- .LP
- Major opcodes 128 through 255 are reserved for extensions.
- Extensions are intended to contain multiple requests,
- so extension requests typically have an additional minor opcode encoded
- in the ``spare'' data byte in the request header,
- but the placement and interpretation of this minor opcode as well as all
- other fields in extension requests are not defined by the core protocol.
- Every request is implicitly assigned a sequence number (starting with one)
- used in replies, errors, and events.
- .LP
- To help but not cure portability problems to certain machines, the
- .PN B16
- and
- .PN B32
- macros have been defined so that they can become bitfield specifications
- on some machines.
- For example, on a Cray,
- these should be used for all 16-bit and 32-bit quantities, as discussed below.
- .LP
- Most protocol requests have a corresponding structure typedef in
- .IN "Files" "<X11/Xproto.h>"
- .Pn < X11/Xproto.h >,
- which looks like:
- .LP
- .IN "xDoSomethingReq" "" "@DEF@"
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- typedef struct _DoSomethingReq {
- CARD8 reqType; /* X_DoSomething */
- CARD8 someDatum; /* used differently in different requests */
- CARD16 length B16; /* total # of bytes in request, divided by 4 */
- ...
- /* request-specific data */
- ...
- } xDoSomethingReq;
- .De
- .\" End marker code here
- .LP
- If a core protocol request has a single 32-bit argument,
- you need not declare a request structure in your extension header file.
- Instead, such requests use
- .Pn < X11/Xproto.h >'s
- .PN xResourceReq
- structure.
- This structure is used for any request whose single argument is a
- .PN Window ,
- .PN Pixmap ,
- .PN Drawable ,
- .PN GContext ,
- .PN Font ,
- .PN Cursor ,
- .PN Colormap ,
- .PN Atom ,
- or
- .PN VisualID .
- .LP
- .IN "xResourceReq" "" "@DEF@"
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- typedef struct _ResourceReq {
- CARD8 reqType; /* the request type, e.g. X_DoSomething */
- BYTE pad; /* not used */
- CARD16 length B16; /* 2 (= total # of bytes in request, divided by 4) */
- CARD32 id B32; /* the Window, Drawable, Font, GContext, etc. */
- } xResourceReq;
- .De
- .\" End marker code here
- .LP
- If convenient,
- you can do something similar in your extension header file.
- .LP
- In both of these structures,
- the reqType field identifies the type of the request (for example,
- X_MapWindow or X_CreatePixmap).
- The length field tells how long the request is
- in units of 4-byte longwords.
- This length includes both the request structure itself and any
- variable length data, such as strings or lists, that follow the
- request structure.
- Request structures come in different sizes,
- but all requests are padded to be multiples of four bytes long.
- .LP
- A few protocol requests take no arguments at all.
- Instead, they use
- .Pn < X11/Xproto.h >'s
- .PN xReq
- structure, which contains only a reqType and a length (and a pad byte).
- .LP
- If the protocol request requires a reply,
- then
- .IN "Files" "<Xproto.h>"
- .Pn < X11/Xproto.h >
- also contains a reply structure typedef:
- .LP
- .IN "xDoSomethingReply" "" "@DEF@"
- .\" Start marker code here
- .Ds 0
- .TA .5i 3i
- .ta .5i 3i
- typedef struct _DoSomethingReply {
- BYTE type; /* always X_Reply */
- BYTE someDatum; /* used differently in different requests */
- CARD16 sequenceNumber B16; /* # of requests sent so far */
- CARD32 length B32; /* # of additional bytes, divided by 4 */
- ...
- /* request-specific data */
- ...
- } xDoSomethingReply;
- .De
- .\" End marker code here
- .LP
- Most of these reply structures are 32 bytes long.
- If there are not that many reply values,
- then they contain a sufficient number of pad fields
- to bring them up to 32 bytes.
- The length field is the total number of bytes in the request minus 32,
- divided by 4.
- This length will be nonzero only if:
- .IP \(bu 5
- The reply structure is followed by variable length
- data such as a list or string.
- .IP \(bu 5
- The reply structure is longer than 32 bytes.
- .LP
- Only
- .PN GetWindowAttributes ,
- .PN QueryFont ,
- .PN QueryKeymap ,
- and
- .PN GetKeyboardControl
- have reply structures longer than 32 bytes in the core protocol.
- .LP
- A few protocol requests return replies that contain no data.
- .IN "Files" "<X11/Xproto.h>"
- .Pn < X11/Xproto.h >
- does not define reply structures for these.
- Instead, they use the
- .PN xGenericReply
- structure, which contains only a type, length,
- and sequence number (and sufficient padding to make it 32 bytes long).
- .SH
- Starting to Write a Stub Routine
- .LP
- An Xlib stub routine should always start like this:
- .LP
- .Ds
- .R
- #include "Xlibint.h"
-
- XDoSomething (arguments, ... )
- /* argument declarations */
- {
-
- register XDoSomethingReq *req;
- ...
- .De
- If the protocol request has a reply,
- then the variable declarations should include the reply structure for the request.
- The following is an example:
- .LP
- .Ds
- .R
- xDoSomethingReply rep;
- .De
- .SH
- Locking Data Structures
- .LP
- To lock the display structure for systems that
- want to support multithreaded access to a single display connection,
- each stub will need to lock its critical section.
- Generally, this section is the point from just before the appropriate GetReq
- call until all arguments to the call have been stored into the buffer.
- The precise instructions needed for this locking depend upon the machine
- architecture.
- Two calls, which are generally implemented as macros, have been provided.
- .IN "LockDisplay" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- LockDisplay(\^\fIdisplay\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .FN
- .LP
- .IN "UnlockDisplay" "" "@DEF@"
- .FD 0
- UnlockDisplay(\^\fIdisplay\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .\" End marker code here
- .SH
- Sending the Protocol Request and Arguments
- .LP
- After the variable declarations,
- a stub routine should call one of four macros defined in
- .IN "Files" "<X11/Xlibint.h>"
- .Pn < X11/Xlibint.h >:
- .PN GetReq ,
- .PN GetReqExtra ,
- .PN GetResReq ,
- or
- .PN GetEmptyReq .
- All of these macros take, as their first argument,
- the name of the protocol request as declared in
- .IN "Files" "<X11/Xproto.h>"
- .Pn < X11/Xproto.h >
- except with X_ removed.
- Each one declares a
- .PN Display
- structure pointer,
- called dpy, and a pointer to a request structure, called req,
- which is of the appropriate type.
- The macro then appends the request structure to the output buffer,
- fills in its type and length field, and sets req to point to it.
- .LP
- If the protocol request has no arguments (for instance, X_GrabServer),
- then use
- .PN GetEmptyReq .
- .LP
- .Ds
- .R
- GetEmptyReq (DoSomething, req);
- .De
- If the protocol request has a single 32-bit argument (such as a
- .PN Pixmap ,
- .PN Window ,
- .PN Drawable ,
- .PN Atom ,
- and so on),
- then use
- .PN GetResReq .
- The second argument to the macro is the 32-bit object.
- .PN X_MapWindow
- is a good example.
- .LP
- .Ds
- .R
- GetResReq (DoSomething, rid, req);
- .De
- The rid argument is the
- .PN Pixmap ,
- .PN Window ,
- or other resource ID.
- .LP
- If the protocol request takes any other argument list,
- then call
- .PN GetReq .
- After the
- .PN GetReq ,
- you need to set all the other fields in the request structure,
- usually from arguments to the stub routine.
- .LP
- .Ds
- .R
- GetReq (DoSomething, req);
- /* fill in arguments here */
- req->arg1 = arg1;
- req->arg2 = arg2;
- ...
- .De
- A few stub routines (such as
- .PN XCreateGC
- and
- .PN XCreatePixmap )
- return a resource ID to the caller but pass a resource ID as an argument
- to the protocol request.
- Such routines use the macro
- .PN XAllocID
- to allocate a resource ID from the range of IDs
- that were assigned to this client when it opened the connection.
- .LP
- .Ds
- .R
- rid = req->rid = XAllocID();
- ...
- return (rid);
- .De
- Finally, some stub routines transmit a fixed amount of variable length
- data after the request.
- Typically, these routines (such as
- .PN XMoveWindow
- and
- .PN XSetBackground )
- are special cases of more general functions like
- .PN XMoveResizeWindow
- and
- .PN XChangeGC .
- These special case routines use
- .PN GetReqExtra ,
- which is the same as
- .PN GetReq
- except that it takes an additional argument (the number of
- extra bytes to allocate in the output buffer after the request structure).
- This number should always be a multiple of four.
- .SH
- Variable Length Arguments
- .LP
- Some protocol requests take additional variable length data that
- follow the
- .PN xDoSomethingReq
- structure.
- The format of this data varies from request to request.
- Some requests require a sequence of 8-bit bytes,
- others a sequence of 16-bit or 32-bit entities,
- and still others a sequence of structures.
- .LP
- It is necessary to add the length of any variable length data to the
- length field of the request structure.
- That length field is in units of 32-bit longwords.
- If the data is a string or other sequence of 8-bit bytes,
- then you must round the length up and shift it before adding:
- .LP
- .Ds
- .R
- req->length += (nbytes+3)>>2;
- .De
- To transmit variable length data, use the
- .PN Data
- macros.
- If the data fits into the output buffer,
- then this macro copies it to the buffer.
- If it does not fit, however,
- the
- .PN Data
- macro calls
- .PN _XSend ,
- which transmits first the contents of the buffer and then your data.
- The
- .PN Data
- macros take three arguments:
- the Display, a pointer to the beginning of the data,
- and the number of bytes to be sent.
- .\" Start marker code here
- .FD 0
- Data(\^\fIdisplay\fP, (char *) \fIdata\fP, \fInbytes\fP\^);
- .sp
- Data16(\^\fIdisplay\fP, (short *) \fIdata\fP, \fInbytes\fP\^);
- .sp
- Data32(\^\fIdisplay\fP, (long *) \fIdata\fP, \fInbytes\fP\^);
- .FN
- .\" End marker code here
- .LP
- .PN Data ,
- .PN Data16 ,
- and
- .PN Data32
- are macros that may use their last argument
- more than once, so that argument should be a variable rather than
- an expression such as ``nitems*sizeof(item)''.
- You should do that kind of computation in a separate statement before calling
- them.
- Use the appropriate macro when sending byte, short, or long data.
- .LP
- If the protocol request requires a reply,
- then call the procedure
- .PN _XSend
- instead of the
- .PN Data
- macro.
- .PN _XSend
- takes the same arguments, but because it sends your data immediately instead of
- copying it into the output buffer (which would later be flushed
- anyway by the following call on
- .PN _XReply ),
- it is faster.
- .SH
- Replies
- .LP
- If the protocol request has a reply,
- then call
- .PN _XReply
- after you have finished dealing with
- all the fixed and variable length arguments.
- .PN _XReply
- flushes the output buffer and waits for an
- .PN xReply
- packet to arrive.
- If any events arrive in the meantime,
- .PN _XReply
- places them in the queue for later use.
- .IN "_XReply" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- Status _XReply(\^\fIdisplay\fP, \fIrep\fP, \fIextra\fP, \fIdiscard\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- xReply *\fIrep\fP\^;
- .br
- int \fIextra\fP\^;
- .br
- Bool \fIdiscard\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIrep\fP 1i
- Specifies the reply structure.
- .IP \fIextra\fP 1i
- Specifies the number of 32-bit words expected after the replay.
- .IP \fIdiscard\fP 1i
- Specifies if beyond the ``extra'' data should be discarded.
- .\" End marker code here
- .LP
- .PN _XReply
- waits for a reply packet and copies its contents into the
- specified rep.
- .PN _XReply
- handles error and event packets that occur before the reply is received.
- .PN _XReply
- takes four arguments:
- .IP \(bu 5
- A
- .PN Display
- * structure
- .IP \(bu 5
- A pointer to a reply structure (which must be cast to an
- .PN xReply
- *)
- .IP \(bu 5
- The number of additional 32-bit words (beyond
- .Pn sizeof( xReply )
- = 32 bytes)
- in the reply structure
- .IP \(bu 5
- A Boolean that indicates whether
- .PN _XReply
- is to discard any additional bytes
- beyond those it was told to read
- .LP
- Because most reply structures are 32 bytes long,
- the third argument is usually 0.
- The only core protocol exceptions are the replies to
- .PN GetWindowAttributes ,
- .PN QueryFont ,
- .PN QueryKeymap ,
- and
- .PN GetKeyboardControl ,
- which have longer replies.
- .LP
- The last argument should be
- .PN False
- if the reply structure is followed
- by additional variable length data (such as a list or string).
- It should be
- .PN True
- if there is not any variable length data.
- .NT
- This last argument is provided for upward-compatibility reasons
- to allow a client to communicate properly with a hypothetical later
- version of the server that sends more data than the client expected.
- For example, some later version of
- .PN GetWindowAttributes
- might use a
- larger, but compatible,
- .PN xGetWindowAttributesReply
- that contains additional attribute data at the end.
- .NE
- .PN _XReply
- returns
- .PN True
- if it received a reply successfully or
- .PN False
- if it received any sort of error.
- .LP
- For a request with a reply that is not followed by variable length
- data, you write something like:
- .LP
- .Ds
- .R
- _XReply(display, (xReply *)&rep, 0, True);
- *ret1 = rep.ret1;
- *ret2 = rep.ret2;
- *ret3 = rep.ret3;
- ...
- UnlockDisplay(dpy);
- SyncHandle();
- return (rep.ret4);
- }
- .De
- If there is variable length data after the reply,
- change the
- .PN True
- to
- .PN False ,
- and use the appropriate
- .PN _XRead
- function to read the variable length data.
- .LP
- .\" Start marker code here
- .FD 0
- _XRead(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
- Display *\fIdisplay\fP\^;
- char *\fIdata_return\fP\^;
- long \fInbytes\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIdata_return\fP 1i
- Specifies the buffer.
- .IP \fInbytes\fP 1i
- Specifies the number of bytes required.
- .\" End marker code here
- .LP
- .PN _XRead
- reads the specified number of bytes into data_return.
- .LP
- .\" Start marker code here
- .FD 0
- _XRead16(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
- Display *\fIdisplay\fP\^;
- short *\fIdata_return\fP\^;
- long \fInbytes\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIdata_return\fP 1i
- Specifies the buffer.
- .IP \fInbytes\fP 1i
- Specifies the number of bytes required.
- .\" End marker code here
- .LP
- .PN _XRead16
- reads the specified number of bytes, unpacking them as 16-bit quantities,
- into the specified array as shorts.
- .LP
- .\" Start marker code here
- .FD 0
- _XRead32(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
- Display *\fIdisplay\fP\^;
- long *\fIdata_return\fP\^;
- long \fInbytes\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIdata_return\fP 1i
- Specifies the buffer.
- .IP \fInbytes\fP 1i
- Specifies the number of bytes required.
- .\" End marker code here
- .LP
- .PN _XRead32
- reads the specified number of bytes, unpacking them as 32-bit quantities,
- into the specified array as longs.
- .LP
- .\" Start marker code here
- .FD 0
- _XRead16Pad(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
- Display *\fIdisplay\fP\^;
- short *\fIdata_return\fP\^;
- long \fInbytes\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIdata_return\fP 1i
- Specifies the buffer.
- .IP \fInbytes\fP 1i
- Specifies the number of bytes required.
- .\" End marker code here
- .LP
- .PN _XRead16Pad
- reads the specified number of bytes, unpacking them as 16-bit quantities,
- into the specified array as shorts.
- If the number of bytes is not a multiple of four,
- .PN _XRead16Pad
- reads and discards up to three additional pad bytes.
- .LP
- .\" Start marker code here
- .FD 0
- _XReadPad(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
- Display *\fIdisplay\fP\^;
- char *\fIdata_return\fP\^;
- long \fInbytes\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fIdata_return\fP 1i
- Specifies the buffer.
- .IP \fInbytes\fP 1i
- Specifies the number of bytes required.
- .\" End marker code here
- .LP
- .PN _XReadPad
- reads the specified number of bytes into data_return.
- If the number of bytes is not a multiple of four,
- .PN _XReadPad
- reads and discards up to three additional pad bytes.
- .LP
- Each protocol request is a little different.
- For further information,
- see the Xlib sources for examples.
- .SH
- Synchronous Calling
- .LP
- To ease debugging,
- each routine should have a call, just before returning to the user,
- to a routine called
- .PN SyncHandle .
- This routine generally is implemented as a macro.
- If synchronous mode is enabled (see
- .PN XSynchronize ),
- the request is sent immediately.
- The library, however, waits until any error the routine could generate
- at the server has been handled.
- .SH
- Allocating and Deallocating Memory
- .LP
- To support the possible reentry of these routines,
- you must observe several conventions when allocating and deallocating memory,
- most often done when returning data to the user from the window
- system of a size the caller could not know in advance
- (for example, a list of fonts or a list of extensions).
- The standard C library routines on many systems
- are not protected against signals or other multithreaded uses.
- The following analogies to standard I/O library routines
- have been defined:
- .IP Xmalloc() 1i
- Replaces malloc()
- .IP XFree() 1i
- Replaces free()
- .IP Xcalloc() 1i
- Replaces calloc()
- .LP
- These should be used in place of any calls you would make to the normal
- C library routines.
- .LP
- If you need a single scratch buffer inside a critical section
- (for example, to pack and unpack data to and from the wire protocol),
- the general memory allocators
- may be too expensive to use (particularly in output routines, which
- are performance critical).
- The routine below returns a scratch buffer for your use:
- .IN "_XAllocScratch" "" "@DEF@"
- .\" Start marker code here
- .FD 0
- char *_XAllocScratch(\^\fIdisplay\fP, \fInbytes\fP\^)
- .br
- Display *\fIdisplay\fP\^;
- .br
- unsigned long \fInbytes\fP\^;
- .FN
- .\" $Header: display.a,v 1.1 88/02/26 10:26:29 mento Exp $
- .IP \fIdisplay\fP 1i
- Specifies the connection to the X server.
- .IP \fInbytes\fP 1i
- Specifies the number of bytes required.
- .\" End marker code here
- .LP
- This storage must only be used inside of the critical section of your
- stub.
- .SH
- Portability Considerations
- .LP
- Many machine architectures,
- including many of the more recent RISC architectures,
- do not correctly access data at unaligned locations;
- their compilers pad out structures to preserve this characteristic.
- Many other machines capable of unaligned references pad inside of structures
- as well to preserve alignment, because accessing aligned data is
- usually much faster.
- Because the library and the server use structures to access data at
- arbitrary points in a byte stream,
- all data in request and reply packets \fImust\fP be naturally aligned;
- that is, 16-bit data starts on 16-bit boundaries in the request
- and 32-bit data on 32-bit boundaries.
- All requests \fImust\fP be a multiple of 32 bits in length to preserve
- the natural alignment in the data stream.
- You must pad structures out to 32-bit boundaries.
- Pad information does not have to be zeroed unless you want to
- preserve such fields for future use in your protocol requests.
- Floating point varies radically between machines and should be
- avoided completely if at all possible.
- .LP
- This code may run on machines with 16-bit ints.
- So, if any integer argument, variable, or return value either can take
- only nonnegative values or is declared as a CARD16 in the protocol,
- be sure to declare it as unsigned int and not as int.
- (This, of course, does not apply to Booleans or enumerations.)
- .LP
- Similarly,
- if any integer argument or return value is declared CARD32 in the protocol,
- declare it as an unsigned long and not as int or long.
- This also goes for any internal variables that may
- take on values larger than the maximum 16-bit unsigned int.
- .LP
- The library currently assumes that a char is 8 bits,
- a short is 16 bits, an int is 16 or 32 bits, and a long is 32 bits.
- The
- .PN PackData
- macro is a half-hearted attempt to deal with the possibility of 32 bit shorts.
- However, much more work is needed to make this work properly.
- .SH
- Deriving the Correct Extension Opcode
- .LP
- The remaining problem a writer of an extension stub routine faces that
- the core protocol does not face is to map from the call to the proper
- major and minor opcodes.
- While there are a number of strategies,
- the simplest and fastest is outlined below.
- .IP 1. 5
- Declare an array of pointers, _NFILE long (this is normally found
- in
- .Pn < stdio.h >
- and is the number of file descriptors supported on the system)
- of type
- .PN XExtCodes .
- Make sure these are all initialized to NULL.
- .IP 2. 5
- When your stub is entered, your initialization test is just to use
- the display pointer passed in to access the file descriptor and an index
- into the array.
- If the entry is NULL, then this is the first time you
- are entering the routine for this display.
- Call your initialization routine and pass it to the display pointer.
- .IP 3. 5
- Once in your initialization routine, call
- .PN XInitExtension ;
- if it succeeds, store the pointer returned into this array.
- Make sure to establish a close display handler to allow you to zero the entry.
- Do whatever other initialization your extension requires.
- (For example, install event handlers and so on.)
- Your initialization routine would normally return a pointer to the
- .PN XExtCodes
- structure for this extension, which is what would normally
- be found in your array of pointers.
- .IP 4. 5
- After returning from your initialization routine,
- the stub can now continue normally, because it has its major opcode safely
- in its hand in the
- .PN XExtCodes
- structure.
- .bp
-