2231 lines
59 KiB
Plaintext
2231 lines
59 KiB
Plaintext
.\" Copyright \(co 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1994, 1996 X Consortium
|
|
.\"
|
|
.\" Permission is hereby granted, free of charge, to any person obtaining
|
|
.\" a copy of this software and associated documentation files (the
|
|
.\" "Software"), to deal in the Software without restriction, including
|
|
.\" without limitation the rights to use, copy, modify, merge, publish,
|
|
.\" distribute, sublicense, and/or sell copies of the Software, and to
|
|
.\" permit persons to whom the Software is furnished to do so, subject to
|
|
.\" the following conditions:
|
|
.\"
|
|
.\" The above copyright notice and this permission notice shall be included
|
|
.\" in all copies or substantial portions of the Software.
|
|
.\"
|
|
.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
.\" IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
.\" OTHER DEALINGS IN THE SOFTWARE.
|
|
.\"
|
|
.\" Except as contained in this notice, the name of the X Consortium shall
|
|
.\" not be used in advertising or otherwise to promote the sale, use or
|
|
.\" other dealings in this Software without prior written authorization
|
|
.\" from the X Consortium.
|
|
.\"
|
|
.\" Copyright \(co 1985, 1986, 1987, 1988, 1989, 1990, 1991 by
|
|
.\" Digital Equipment Corporation
|
|
.\"
|
|
.\" Portions Copyright \(co 1990, 1991 by
|
|
.\" Tektronix, Inc.
|
|
.\"
|
|
.\" Permission to use, copy, modify and distribute this documentation for
|
|
.\" any purpose and without fee is hereby granted, provided that the above
|
|
.\" copyright notice appears in all copies and that both that copyright notice
|
|
.\" and this permission notice appear in all copies, and that the names of
|
|
.\" Digital and Tektronix not be used in in advertising or publicity pertaining
|
|
.\" to this documentation without specific, written prior permission.
|
|
.\" Digital and Tektronix makes no representations about the suitability
|
|
.\" of this documentation for any purpose.
|
|
.\" It is provided ``as is'' without express or implied warranty.
|
|
.\"
|
|
\&
|
|
.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,
|
|
automatically initializing 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 10 new features as 10 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
|
|
.hN X11/Xlibint.h .
|
|
.SH
|
|
Basic Protocol Support Routines
|
|
.LP
|
|
The basic protocol requests for extensions are
|
|
.PN XQueryExtension
|
|
and
|
|
.PN XListExtensions .
|
|
.IN "XQueryExtension" "" "@DEF@"
|
|
.sM
|
|
.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
|
|
.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 \fIfirst_error_return\fP 1i
|
|
Returns the first error code, if any.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XQueryExtension
|
|
function determines if the named extension is present.
|
|
If the extension is not present,
|
|
.PN XQueryExtension
|
|
returns
|
|
.PN False ;
|
|
otherwise, it returns
|
|
.PN True .
|
|
If the extension is present,
|
|
.PN XQueryExtension
|
|
returns the major opcode for the extension to major_opcode_return;
|
|
otherwise,
|
|
it returns zero.
|
|
Any minor opcode and the request formats are specific to the
|
|
extension.
|
|
If the extension involves additional event types,
|
|
.PN XQueryExtension
|
|
returns the base event type code to first_event_return;
|
|
otherwise,
|
|
it returns zero.
|
|
The format of the events is specific to the extension.
|
|
If the extension involves additional error codes,
|
|
.PN XQueryExtension
|
|
returns the base error code to first_error_return;
|
|
otherwise,
|
|
it returns zero.
|
|
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.
|
|
Uppercase and lowercase matter;
|
|
the strings ``thing'', ``Thing'', and ``thinG''
|
|
are all considered different names.
|
|
.IN "XListExtensions" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
char **XListExtensions(\^\fIdisplay\fP, \fInextensions_return\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int *\fInextensions_return\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fInextensions_return\fP 1i
|
|
Returns the number of extensions listed.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XListExtensions
|
|
function 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@"
|
|
.sM
|
|
.FD 0
|
|
XFreeExtensionList(\^\fIlist\fP\^)
|
|
.br
|
|
char **\fIlist\fP\^;
|
|
.FN
|
|
.IP \fIlist\fP 1i
|
|
Specifies the list of extension names.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XFreeExtensionList
|
|
function 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
|
|
.hN X11/Xlib.h :
|
|
.LP
|
|
.IN "XExtCodes" "" "@DEF@"
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
.IN "XInitExtension" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
XExtCodes *XInitExtension(\^\fIdisplay\fP, \fIname\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
char *\fIname\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fIname\fP 1i
|
|
Specifies the extension name.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XInitExtension
|
|
function 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.
|
|
Uppercase and lowercase matter;
|
|
the strings ``thing'', ``Thing'', and ``thinG''
|
|
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@"
|
|
.sM
|
|
.FD 0
|
|
XExtCodes *XAddExtension\^(\^\fIdisplay\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.LP
|
|
.eM
|
|
For local Xlib extensions, the
|
|
.PN XAddExtension
|
|
function 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 procedure defined for this
|
|
extension.
|
|
.IN "XESetCloseDisplay" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetCloseDisplay(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int (\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when the display is closed.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetCloseDisplay
|
|
function defines a procedure to be called whenever
|
|
.PN XCloseDisplay
|
|
is called.
|
|
It returns any previously defined procedure, usually NULL.
|
|
.LP
|
|
When
|
|
.PN XCloseDisplay
|
|
is called,
|
|
your procedure is called
|
|
with these arguments:
|
|
.LP
|
|
.sM
|
|
.Ds 0
|
|
.TA .5i 3i
|
|
.ta .5i 3i
|
|
.R
|
|
(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIcodes\fP\^)
|
|
Display *\fIdisplay\fP\^;
|
|
XExtCodes *\fIcodes\fP\^;
|
|
.De
|
|
.LP
|
|
.eM
|
|
.IN "XESetCreateGC" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetCreateGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int (\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when a GC is closed.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetCreateGC
|
|
function defines a procedure to be called whenever
|
|
a new GC is created.
|
|
It returns any previously defined procedure, usually NULL.
|
|
.LP
|
|
When a GC is created,
|
|
your procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
.IN "XESetCopyGC" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetCopyGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int (\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when GC components are copied.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetCopyGC
|
|
function defines a procedure to be called whenever
|
|
a GC is copied.
|
|
It returns any previously defined procedure, usually NULL.
|
|
.LP
|
|
When a GC is copied,
|
|
your procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
.IN "XESetFreeGC" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetFreeGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc)\fP\^)(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int (\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when a GC is freed.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetFreeGC
|
|
function defines a procedure to be called whenever
|
|
a GC is freed.
|
|
It returns any previously defined procedure, usually NULL.
|
|
.LP
|
|
When a GC is freed,
|
|
your procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
.IN "XESetCreateFont" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetCreateFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int (\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when a font is created.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetCreateFont
|
|
function defines a procedure to be called whenever
|
|
.PN XLoadQueryFont
|
|
and
|
|
.PN XQueryFont
|
|
are called.
|
|
It returns any previously defined procedure, usually NULL.
|
|
.LP
|
|
When
|
|
.PN XLoadQueryFont
|
|
or
|
|
.PN XQueryFont
|
|
is called,
|
|
your procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
.IN "XESetFreeFont" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetFreeFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int (\^*\fIproc\fP)(\^);
|
|
.FN
|
|
.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 procedure to call when a font is freed.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetFreeFont
|
|
function defines a procedure to be called whenever
|
|
.PN XFreeFont
|
|
is called.
|
|
It returns any previously defined procedure, usually NULL.
|
|
.LP
|
|
When
|
|
.PN XFreeFont
|
|
is called, your procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetWireToEvent
|
|
and
|
|
.PN XESetEventToWire
|
|
functions allow you to define new events to the library.
|
|
An
|
|
.PN XEvent
|
|
structure always has a type code (type
|
|
.PN int )
|
|
as the first component.
|
|
This uniquely identifies what kind of event it is.
|
|
The second component is always the serial number (type
|
|
.PN unsigned
|
|
.PN long )
|
|
of the last request processed by the server.
|
|
The third component is always a Boolean (type
|
|
.PN 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@"
|
|
.sM
|
|
.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
|
|
.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 procedure to call when converting an event.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetWireToEvent
|
|
function defines 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 procedure for.
|
|
.PN XESetWireToEvent
|
|
returns any previously defined procedure.
|
|
.NT
|
|
You can replace a core event conversion function 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 procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
Your procedure 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 procedure 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@"
|
|
.sM
|
|
.FD 0
|
|
unsigned long _XSetLastRequestRead(\^\fIdisplay\fP, \fIrep\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
xGenericReply *\fIrep\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fIrep\fP 1i
|
|
Specifies the wire event structure.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN _XSetLastRequestRead
|
|
function computes and returns a complete serial number from the partial
|
|
serial number in the event.
|
|
.sp
|
|
.LP
|
|
.IN "XESetEventToWire" "" "@DEF@"
|
|
.sM
|
|
.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
|
|
.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 procedure to call when converting an event.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetEventToWire
|
|
function defines 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 procedure for.
|
|
.PN XESetEventToWire
|
|
returns any previously defined procedure.
|
|
It returns zero if the conversion fails or nonzero otherwise.
|
|
.NT
|
|
You can replace a core event conversion function 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 procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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@"
|
|
.sM
|
|
.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
|
|
.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 procedure to call when an error is received.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetWireToError
|
|
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 procedure for.
|
|
.PN XESetWireToError
|
|
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 procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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
|
|
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@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetError(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int (\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when an error is received.
|
|
.LP
|
|
.eM
|
|
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 functions 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
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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 procedure 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 procedure returns nonzero,
|
|
the error is suppressed, and
|
|
.PN _XReply
|
|
returns the value of ret_code.
|
|
.IN "XESetErrorString" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
char *(*XESetErrorString(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
char *(\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call to obtain an error string.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XGetErrorText
|
|
function returns a string to the user for an error.
|
|
.PN XESetErrorString
|
|
allows you to define a procedure to be called that
|
|
should return a pointer to the error message.
|
|
The following is an example.
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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@"
|
|
.sM
|
|
.FD 0
|
|
void (*XESetPrintErrorValues(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
void (\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when an error is printed.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetPrintErrorValues
|
|
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.
|
|
It returns any previously defined procedure.
|
|
.LP
|
|
When Xlib needs to print an error,
|
|
the procedure is called with these arguments:
|
|
.LP
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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
|
|
to obtain additional values set by using
|
|
.PN XESetWireToError .
|
|
The underlying type of the fp argument is system dependent;
|
|
on a POSIX-compliant system, fp should be cast to type FILE*.
|
|
.IN "XESetFlushGC" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetFlushGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int *(\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when a GC is flushed.
|
|
.LP
|
|
.eM
|
|
The procedure set by the
|
|
.PN XESetFlushGC
|
|
function has the same interface as the procedure set by the
|
|
.PN XESetCopyGC
|
|
function, but is called when a GC cache needs to be updated in the server.
|
|
.IN "XESetBeforeFlush" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
int (*XESetBeforeFlush(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
int \fIextension\fP\^;
|
|
.br
|
|
int *(\^*\fIproc\fP\^)(\^);
|
|
.FN
|
|
.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 procedure to call when a buffer is flushed.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XESetBeforeFlush
|
|
function defines a procedure to be called when data is about to be
|
|
sent to the server. When data is about to be sent, your procedure is
|
|
called one or more times with these arguments:
|
|
.LP
|
|
.sM
|
|
.Ds 0
|
|
.TA .5i 3i
|
|
.ta .5i 3i
|
|
.R
|
|
void (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIcodes\fP, \fIdata\fP, \fIlen\fP\^)
|
|
Display *\fIdisplay\fP\^;
|
|
XExtCodes *\fIcodes\fP\^;
|
|
char *\fIdata\fP\^;
|
|
long \fIlen\fP\^;
|
|
.De
|
|
.LP
|
|
.eM
|
|
The data argument specifies a portion of the outgoing data buffer,
|
|
and its length in bytes is specified by the len argument.
|
|
Your procedure must not alter the contents of the data and must not
|
|
do additional protocol requests to the same display.
|
|
.SH
|
|
Hooks onto Xlib Data Structures
|
|
.LP
|
|
Various Xlib data structures have provisions for extension procedures
|
|
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 procedures can be used to manipulate the data
|
|
on these lists.
|
|
.LP
|
|
The following structure is used in the functions in this section
|
|
and is defined in
|
|
.hN X11/Xlib.h :
|
|
.LP
|
|
.IN "XExtData" "" "@DEF@"
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
When any of the data structures listed above are freed,
|
|
the list is walked, and the structure's free procedure (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
|
|
.sM
|
|
.Ds 0
|
|
.TA .5i
|
|
.ta .5i
|
|
union { Display *display;
|
|
GC gc;
|
|
Visual *visual;
|
|
Screen *screen;
|
|
ScreenFormat *pixmap_format;
|
|
XFontStruct *font } XEDataObject;
|
|
.De
|
|
.LP
|
|
.eM
|
|
.IN "XEHeadOfExtensionList" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
XExtData **XEHeadOfExtensionList(\^\fIobject\fP\^)
|
|
XEDataObject \fIobject\fP\^;
|
|
.FN
|
|
.IP \fIobject\fP 1i
|
|
Specifies the object.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XEHeadOfExtensionList
|
|
function 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@"
|
|
.sM
|
|
.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.
|
|
.LP
|
|
.eM
|
|
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 function.
|
|
.IN "XFindOnExtensionList" "" "@DEF@"
|
|
.sM
|
|
.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
|
|
.PN XInitExtension .
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN XFindOnExtensionList
|
|
function 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
|
|
.hN X11/Xlib.h .
|
|
.IN "XAllocID" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
XAllocID\^(\fIdisplay\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.LP
|
|
.eM
|
|
This macro is a call through the
|
|
.PN Display
|
|
structure to an internal resource ID allocator.
|
|
It returns a resource ID that you can use when creating new resources.
|
|
.LP
|
|
The
|
|
.PN XAllocIDs
|
|
macro allocates and returns an array of resource ID.
|
|
.IN "XAllocIDs" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
XAllocIDs\^(\fIdisplay\fP, \fIids_return\fP, \fIcount\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
XID *\fIids_return\fP\^;
|
|
.br
|
|
int \fIcount\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fIids_return\fP 1i
|
|
Returns the resource IDs.
|
|
.IP \fIrep\fP 1i
|
|
Specifies the number of resource IDs requested.
|
|
.LP
|
|
.eM
|
|
This macro is a call through the
|
|
.PN Display
|
|
structure to an internal resource ID allocator.
|
|
It returns resource IDs to the array supplied by the caller.
|
|
To correctly handle automatic reuse of resource IDs, you must call
|
|
.PN XAllocIDs
|
|
when requesting multiple resource IDs. This call might generate
|
|
protocol requests.
|
|
.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 procedure 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@"
|
|
.sM
|
|
.FD 0
|
|
FlushGC\^(\^\fIdisplay\fP\^, \fIgc\fP\^)
|
|
.br
|
|
Display *\^\fIdisplay\fP\^;
|
|
.br
|
|
GC \fIgc\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fIgc\fP 1i
|
|
Specifies the GC.
|
|
.LP
|
|
.eM
|
|
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@"
|
|
.sM
|
|
.FD 0
|
|
_XFlushGCCache\^(\^\fIdisplay\fP\^, \fIgc\fP\^)
|
|
.br
|
|
Display *\^\fIdisplay\fP\^;
|
|
.br
|
|
GC \fIgc\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fIgc\fP 1i
|
|
Specifies the GC.
|
|
.LP
|
|
.eM
|
|
.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
|
|
.sM
|
|
.nf
|
|
|
|
#include <X11/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
|
|
.LP
|
|
.eM
|
|
To keep clients from generating very long requests that may monopolize the
|
|
server,
|
|
there is a symbol defined in
|
|
.hN 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
|
|
.hN 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
|
|
.hN X11/Xproto.h
|
|
for your extension and need to include it in your stub procedure.
|
|
Each stub procedure also must include
|
|
.hN 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
|
|
.hN X11/Xlibint.h ,
|
|
takes advantage of this naming scheme.
|
|
.LP
|
|
For each X request,
|
|
there is a definition in
|
|
.hN 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 4 bytes.
|
|
Every request consists of 4 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 second 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
|
|
.hN X11/Xproto.h ,
|
|
which looks like:
|
|
.LP
|
|
.IN "xDoSomethingReq" "" "@DEF@"
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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 the
|
|
.PN xResourceReq
|
|
structure in
|
|
.hN X11/Xproto.h .
|
|
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@"
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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 the
|
|
.PN xReq
|
|
structure in
|
|
.hN X11/Xproto.h ,
|
|
which contains only a reqType and a length (and a pad byte).
|
|
.LP
|
|
If the protocol request requires a reply,
|
|
then
|
|
.hN X11/Xproto.h
|
|
also contains a reply structure typedef:
|
|
.LP
|
|
.IN "xDoSomethingReply" "" "@DEF@"
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
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.
|
|
.hN 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 Procedure
|
|
.LP
|
|
An Xlib stub procedure should start like this:
|
|
.LP
|
|
.Ds
|
|
.R
|
|
#include "<X11/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@"
|
|
.sM
|
|
.FD 0
|
|
LockDisplay(\^\fIdisplay\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.FN
|
|
.LP
|
|
.IN "UnlockDisplay" "" "@DEF@"
|
|
.FD 0
|
|
UnlockDisplay(\^\fIdisplay\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.LP
|
|
.eM
|
|
.SH
|
|
Sending the Protocol Request and Arguments
|
|
.LP
|
|
After the variable declarations,
|
|
a stub procedure should call one of four macros defined in
|
|
.hN 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
|
|
.hN 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 procedure.
|
|
.LP
|
|
.Ds
|
|
.R
|
|
GetReq (DoSomething, req);
|
|
/* fill in arguments here */
|
|
req->arg1 = arg1;
|
|
req->arg2 = arg2;
|
|
\^...
|
|
.De
|
|
A few stub procedures (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 procedures 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 procedures transmit a fixed amount of variable-length
|
|
data after the request.
|
|
Typically, these procedures (such as
|
|
.PN XMoveWindow
|
|
and
|
|
.PN XSetBackground )
|
|
are special cases of more general functions like
|
|
.PN XMoveResizeWindow
|
|
and
|
|
.PN XChangeGC .
|
|
These procedures 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.
|
|
.sM
|
|
.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
|
|
.LP
|
|
.eM
|
|
.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-length 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@"
|
|
.sM
|
|
.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
|
|
.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 any data beyond that specified in the extra argument
|
|
should be discarded.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN _XReply
|
|
function 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
|
|
.sM
|
|
.FD 0
|
|
_XRead(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
|
|
Display *\fIdisplay\fP\^;
|
|
char *\fIdata_return\fP\^;
|
|
long \fInbytes\fP\^;
|
|
.FN
|
|
.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.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN _XRead
|
|
function reads the specified number of bytes into data_return.
|
|
.LP
|
|
.sM
|
|
.FD 0
|
|
_XRead16(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
|
|
Display *\fIdisplay\fP\^;
|
|
short *\fIdata_return\fP\^;
|
|
long \fInbytes\fP\^;
|
|
.FN
|
|
.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.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN _XRead16
|
|
function reads the specified number of bytes,
|
|
unpacking them as 16-bit quantities,
|
|
into the specified array as shorts.
|
|
.LP
|
|
.sM
|
|
.FD 0
|
|
_XRead32(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
|
|
Display *\fIdisplay\fP\^;
|
|
long *\fIdata_return\fP\^;
|
|
long \fInbytes\fP\^;
|
|
.FN
|
|
.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.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN _XRead32
|
|
function reads the specified number of bytes,
|
|
unpacking them as 32-bit quantities,
|
|
into the specified array as longs.
|
|
.LP
|
|
.sM
|
|
.FD 0
|
|
_XRead16Pad(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
|
|
Display *\fIdisplay\fP\^;
|
|
short *\fIdata_return\fP\^;
|
|
long \fInbytes\fP\^;
|
|
.FN
|
|
.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.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN _XRead16Pad
|
|
function 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 two additional pad bytes.
|
|
.LP
|
|
.sM
|
|
.FD 0
|
|
_XReadPad(\^\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP\^)
|
|
Display *\fIdisplay\fP\^;
|
|
char *\fIdata_return\fP\^;
|
|
long \fInbytes\fP\^;
|
|
.FN
|
|
.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.
|
|
.LP
|
|
.eM
|
|
The
|
|
.PN _XReadPad
|
|
function 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
|
|
Each procedure should have a call, just before returning to the user,
|
|
to a macro called
|
|
.PN SyncHandle .
|
|
If synchronous mode is enabled (see
|
|
.PN XSynchronize ),
|
|
the request is sent immediately.
|
|
The library, however, waits until any error the procedure could generate
|
|
at the server has been handled.
|
|
.SH
|
|
Allocating and Deallocating Memory
|
|
.LP
|
|
To support the possible reentry of these procedures,
|
|
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 functions on many systems
|
|
are not protected against signals or other multithreaded uses.
|
|
The following analogies to standard I/O library functions
|
|
have been defined:
|
|
.TS
|
|
l l.
|
|
T{
|
|
.PN Xmalloc ()
|
|
T} T{
|
|
Replaces
|
|
.PN malloc ()
|
|
T}
|
|
T{
|
|
.PN XFree ()
|
|
T} T{
|
|
Replaces
|
|
.PN free ()
|
|
T}
|
|
T{
|
|
.PN Xcalloc ()
|
|
T} T{
|
|
Replaces
|
|
.PN calloc ()
|
|
T}
|
|
.TE
|
|
.LP
|
|
These should be used in place of any calls you would make to the normal
|
|
C library functions.
|
|
.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 functions, which are performance critical).
|
|
The following function returns a scratch buffer for use within a
|
|
critical section:
|
|
.IN "_XAllocScratch" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
char *_XAllocScratch(\^\fIdisplay\fP, \fInbytes\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
unsigned long \fInbytes\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fInbytes\fP 1i
|
|
Specifies the number of bytes required.
|
|
.LP
|
|
.eM
|
|
This storage must only be used inside of a critical section of your
|
|
stub. The returned pointer cannot be assumed valid after any call
|
|
that might permit another thread to execute inside Xlib. For example,
|
|
the pointer cannot be assumed valid after any use of the
|
|
.PN GetReq
|
|
or
|
|
.PN Data
|
|
families of macros,
|
|
after any use of
|
|
.PN _XReply ,
|
|
or after any use of the
|
|
.PN _XSend
|
|
or
|
|
.PN _XRead
|
|
families of functions.
|
|
.LP
|
|
.sp
|
|
The following function returns a scratch buffer for use across
|
|
critical sections:
|
|
.IN "_XAllocTemp" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
char *_XAllocTemp(\^\fIdisplay\fP, \fInbytes\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
unsigned long \fInbytes\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fInbytes\fP 1i
|
|
Specifies the number of bytes required.
|
|
.LP
|
|
.eM
|
|
This storage can be used across calls that might permit another thread to
|
|
execute inside Xlib. The storage must be explicitly returned to Xlib.
|
|
The following function returns the storage:
|
|
.IN "_XFreeTemp" "" "@DEF@"
|
|
.sM
|
|
.FD 0
|
|
void _XFreeTemp(\^\fIdisplay\fP, \fIbuf\fP, \fInbytes\fP\^)
|
|
.br
|
|
Display *\fIdisplay\fP\^;
|
|
.br
|
|
char *\fIbuf\fP\^;
|
|
.br
|
|
unsigned long \fInbytes\fP\^;
|
|
.FN
|
|
.IP \fIdisplay\fP 1i
|
|
Specifies the connection to the X server.
|
|
.IP \fIbuf\fP 1i
|
|
Specifies the buffer to return.
|
|
.IP \fInbytes\fP 1i
|
|
Specifies the size of the buffer.
|
|
.LP
|
|
.eM
|
|
You must pass back the same pointer and size that were returned by
|
|
.PN _XAllocTemp .
|
|
.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
|
|
.PN CARD16
|
|
in the protocol, be sure to declare it as
|
|
.PN unsigned
|
|
.PN int
|
|
and not as
|
|
.PN int .
|
|
(This, of course, does not apply to Booleans or enumerations.)
|
|
.LP
|
|
Similarly,
|
|
if any integer argument or return value is declared
|
|
.PN CARD32
|
|
in the protocol,
|
|
declare it as an
|
|
.PN unsigned
|
|
.PN long
|
|
and not as
|
|
.PN int
|
|
or
|
|
.PN long .
|
|
This also goes for any internal variables that may
|
|
take on values larger than the maximum 16-bit
|
|
.PN unsigned
|
|
.PN int .
|
|
.LP
|
|
The library currently assumes that a
|
|
.PN char
|
|
is 8 bits, a
|
|
.PN short
|
|
is 16 bits, an
|
|
.PN int
|
|
is 16 or 32 bits, and a
|
|
.PN 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 procedure 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
|
|
.hN 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 procedure for this display.
|
|
Call your initialization procedure and pass to it the display pointer.
|
|
.IP 3. 5
|
|
Once in your initialization procedure, 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 procedure 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 procedure,
|
|
the stub can now continue normally, because it has its major opcode safely
|
|
in its hand in the
|
|
.PN XExtCodes
|
|
structure.
|
|
.bp
|