#define NEED_EVENTS
#define NEED_REPLIES
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/Xlibint.h>
#include <stdio.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include <X11/extensions/multibufst.h>
static XExtensionInfo _multibuf_info_data;
static XExtensionInfo *multibuf_info = &_multibuf_info_data;
static char *multibuf_extension_name = MULTIBUFFER_PROTOCOL_NAME;
#define MbufCheckExtension(dpy,i,val) \
XextCheckExtension (dpy, i, multibuf_extension_name, val)
#define MbufSimpleCheckExtension(dpy,i) \
XextSimpleCheckExtension (dpy, i, multibuf_extension_name)
static int close_display(Display *dpy, XExtCodes *codes);
static char *error_string(Display *dpy, int code, XExtCodes *codes, char *buf, int n);
static Bool wire_to_event(Display *dpy, XEvent *libevent, xEvent *netevent);
static Status event_to_wire(Display *dpy, XEvent *libevent, xEvent *netevent);
static XExtensionHooks multibuf_extension_hooks = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
close_display,
wire_to_event,
event_to_wire,
NULL,
error_string,
};
static char *multibuf_error_list[] = {
"BadBuffer",
};
static XEXT_GENERATE_FIND_DISPLAY (find_display, multibuf_info,
multibuf_extension_name,
&multibuf_extension_hooks,
MultibufferNumberEvents, NULL)
static XEXT_GENERATE_CLOSE_DISPLAY (close_display, multibuf_info)
static XEXT_GENERATE_ERROR_STRING (error_string, multibuf_extension_name,
MultibufferNumberErrors,
multibuf_error_list)
static Bool wire_to_event (Display *dpy, XEvent *libevent, xEvent *netevent)
{
XExtDisplayInfo *info = find_display (dpy);
MbufCheckExtension (dpy, info, False);
switch ((netevent->u.u.type & 0x7f) - info->codes->first_event) {
case MultibufferClobberNotify:
{
XmbufClobberNotifyEvent *ev;
xMbufClobberNotifyEvent *event;
ev = (XmbufClobberNotifyEvent *) libevent;
event = (xMbufClobberNotifyEvent *) netevent;
ev->type = event->type & 0x7f;
ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
ev->send_event = ((event->type & 0x80) != 0);
ev->display = dpy;
ev->buffer = event->buffer;
ev->state = event->state;
return True;
}
case MultibufferUpdateNotify:
{
XmbufUpdateNotifyEvent *ev;
xMbufUpdateNotifyEvent *event;
ev = (XmbufUpdateNotifyEvent *) libevent;
event = (xMbufUpdateNotifyEvent *) netevent;
ev->type = event->type & 0x7f;
ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
ev->send_event = ((event->type & 0x80) != 0);
ev->display = dpy;
ev->buffer = event->buffer;
return True;
}
}
return False;
}
static Status event_to_wire (Display *dpy, XEvent *libevent, xEvent *netevent)
{
XExtDisplayInfo *info = find_display (dpy);
MbufCheckExtension (dpy, info, 0);
switch ((libevent->type & 0x7f) - info->codes->first_event) {
case MultibufferClobberNotify:
{
XmbufClobberNotifyEvent *ev;
xMbufClobberNotifyEvent *event;
ev = (XmbufClobberNotifyEvent *) libevent;
event = (xMbufClobberNotifyEvent *) netevent;
event->type = ev->type;
event->sequenceNumber = (ev->serial & 0xffff);
event->buffer = ev->buffer;
event->state = ev->state;
return 1;
}
case MultibufferUpdateNotify:
{
XmbufUpdateNotifyEvent *ev;
xMbufUpdateNotifyEvent *event;
ev = (XmbufUpdateNotifyEvent *) libevent;
event = (xMbufUpdateNotifyEvent *) netevent;
event->type = ev->type;
event->sequenceNumber = (ev->serial & 0xffff);
event->buffer = ev->buffer;
return 1;
}
}
return 0;
}
#define TALLOC(type,count) ((type *) Xmalloc ((unsigned) count * sizeof(type)))
static XmbufBufferInfo *read_buffer_info (Display *dpy, int nbufs)
{
xMbufBufferInfo *netbuf = TALLOC (xMbufBufferInfo, nbufs);
XmbufBufferInfo *bufinfo = NULL;
long netbytes = nbufs * SIZEOF(xMbufBufferInfo);
if (netbuf) {
_XRead (dpy, (char *) netbuf, netbytes);
bufinfo = TALLOC (XmbufBufferInfo, nbufs);
if (bufinfo) {
register XmbufBufferInfo *c;
register xMbufBufferInfo *net;
register int i;
for (i = 0, c = bufinfo, net = netbuf; i < nbufs;
i++, c++, net++) {
c->visualid = net->visualID;
c->max_buffers = net->maxBuffers;
c->depth = net->depth;
}
}
Xfree ((char *) netbuf);
} else {
while (netbytes > 0) {
char dummy[256];
long nbytes = sizeof dummy;
if (nbytes > netbytes) nbytes = netbytes;
_XRead (dpy, dummy, nbytes);
netbytes -= nbytes;
}
}
return bufinfo;
}
#undef TALLOC
Bool XmbufQueryExtension (
Display *dpy,
int *event_base_return, int *error_base_return)
{
XExtDisplayInfo *info = find_display (dpy);
if (XextHasExtension (info)) {
*event_base_return = info->codes->first_event;
*error_base_return = info->codes->first_error;
return True;
} else {
return False;
}
}
Status XmbufGetVersion (
Display *dpy,
int *major_version_return, int *minor_version_return)
{
XExtDisplayInfo *info = find_display (dpy);
xMbufGetBufferVersionReply rep;
register xMbufGetBufferVersionReq *req;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetBufferVersion, req, info);
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
*major_version_return = rep.majorVersion;
*minor_version_return = rep.minorVersion;
UnlockDisplay (dpy);
SyncHandle ();
return 1;
}
int XmbufCreateBuffers (
Display *dpy,
Window w,
int count,
int update_action, int update_hint,
Multibuffer *buffers)
{
XExtDisplayInfo *info = find_display (dpy);
xMbufCreateImageBuffersReply rep;
register xMbufCreateImageBuffersReq *req;
int result;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
XAllocIDs(dpy, buffers, count);
MbufGetReq (MbufCreateImageBuffers, req, info);
req->window = w;
req->updateAction = update_action;
req->updateHint = update_hint;
req->length += count;
count <<= 2;
PackData32 (dpy, buffers, count);
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
result = rep.numberBuffer;
UnlockDisplay (dpy);
SyncHandle ();
return result;
}
void XmbufDestroyBuffers (Display *dpy, Window window)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufDestroyImageBuffersReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufDestroyImageBuffers, req, info);
req->window = window;
UnlockDisplay (dpy);
SyncHandle ();
}
void XmbufDisplayBuffers (
Display *dpy,
int count,
Multibuffer *buffers,
int min_delay, int max_delay)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufDisplayImageBuffersReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufDisplayImageBuffers, req, info);
req->minDelay = min_delay;
req->maxDelay = max_delay;
req->length += count;
count <<= 2;
PackData32 (dpy, buffers, count);
UnlockDisplay (dpy);
SyncHandle();
}
Status XmbufGetWindowAttributes (
Display *dpy,
Window w,
XmbufWindowAttributes *attr)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufGetMBufferAttributesReq *req;
xMbufGetMBufferAttributesReply rep;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetMBufferAttributes, req, info);
req->window = w;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
attr->buffers = (Multibuffer *) NULL;
if ((attr->nbuffers = rep.length)) {
int nbytes = rep.length * sizeof(Multibuffer);
attr->buffers = (Multibuffer *) Xmalloc((unsigned) nbytes);
nbytes = rep.length << 2;
if (! attr->buffers) {
_XEatData(dpy, (unsigned long) nbytes);
UnlockDisplay(dpy);
SyncHandle();
return (0);
}
_XRead32 (dpy, (long *) attr->buffers, nbytes);
}
attr->displayed_index = rep.displayedBuffer;
attr->update_action = rep.updateAction;
attr->update_hint = rep.updateHint;
attr->window_mode = rep.windowMode;
UnlockDisplay (dpy);
SyncHandle();
return 1;
}
void XmbufChangeWindowAttributes (
Display *dpy,
Window w,
unsigned long valuemask,
XmbufSetWindowAttributes *attr)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufSetMBufferAttributesReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufSetMBufferAttributes, req, info);
req->window = w;
if ((req->valueMask = valuemask)) {
unsigned long values[1];
unsigned long *v = values;
unsigned int nvalues;
if (valuemask & MultibufferWindowUpdateHint)
*v++ = attr->update_hint;
req->length += (nvalues = v - values);
nvalues <<= 2;
Data32 (dpy, (long *) values, (long)nvalues);
}
UnlockDisplay (dpy);
SyncHandle();
}
Status XmbufGetBufferAttributes (
Display *dpy,
Multibuffer b,
XmbufBufferAttributes *attr)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufGetBufferAttributesReq *req;
xMbufGetBufferAttributesReply rep;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetBufferAttributes, req, info);
req->buffer = b;
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
attr->window = rep.window;
attr->event_mask = rep.eventMask;
attr->buffer_index = rep.bufferIndex;
attr->side = rep.side;
UnlockDisplay (dpy);
SyncHandle();
return 1;
}
void XmbufChangeBufferAttributes (
Display *dpy,
Multibuffer b,
unsigned long valuemask,
XmbufSetBufferAttributes *attr)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufSetBufferAttributesReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufSetBufferAttributes, req, info);
req->buffer = b;
if ((req->valueMask = valuemask)) {
unsigned long values[1];
unsigned long *v = values;
unsigned int nvalues;
if (valuemask & MultibufferBufferEventMask)
*v++ = attr->event_mask;
req->length += (nvalues = v - values);
nvalues <<= 2;
Data32 (dpy, (long *) values, (long)nvalues);
}
UnlockDisplay (dpy);
SyncHandle();
}
Status XmbufGetScreenInfo (
Display *dpy,
Drawable d,
int *nmono_return,
XmbufBufferInfo **mono_info_return,
int *nstereo_return,
XmbufBufferInfo **stereo_info_return)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufGetBufferInfoReq *req;
xMbufGetBufferInfoReply rep;
int nmono, nstereo;
XmbufBufferInfo *minfo, *sinfo;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetBufferInfo, req, info);
req->drawable = d;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
nmono = rep.normalInfo;
nstereo = rep.stereoInfo;
minfo = ((nmono > 0) ? read_buffer_info (dpy, nmono) : NULL);
sinfo = ((nstereo > 0) ? read_buffer_info (dpy, nstereo) : NULL);
if ((nmono > 0 && !minfo) || (nstereo > 0 && !sinfo)) {
if (minfo) Xfree ((char *) minfo);
if (sinfo) Xfree ((char *) sinfo);
UnlockDisplay (dpy);
SyncHandle();
return 0;
}
*nmono_return = nmono;
*mono_info_return = minfo;
*nstereo_return = nstereo;
*stereo_info_return = sinfo;
UnlockDisplay (dpy);
SyncHandle();
return 1;
}
Window XmbufCreateStereoWindow (
Display *dpy,
Window parent,
int x, int y,
unsigned int width, unsigned int height, unsigned int border_width,
int depth,
unsigned int class,
Visual *visual,
unsigned long valuemask,
XSetWindowAttributes *attr,
Multibuffer *leftp, Multibuffer *rightp)
{
XExtDisplayInfo *info = find_display (dpy);
Window wid;
register xMbufCreateStereoWindowReq *req;
MbufCheckExtension (dpy, info, None);
LockDisplay(dpy);
MbufGetReq(MbufCreateStereoWindow, req, info);
wid = req->wid = XAllocID(dpy);
req->parent = parent;
req->left = *leftp = XAllocID (dpy);
req->right = *rightp = XAllocID (dpy);
req->x = x;
req->y = y;
req->width = width;
req->height = height;
req->borderWidth = border_width;
req->depth = depth;
req->class = class;
if (visual == CopyFromParent)
req->visual = CopyFromParent;
else
req->visual = visual->visualid;
valuemask &= (CWBackPixmap|CWBackPixel|CWBorderPixmap|
CWBorderPixel|CWBitGravity|CWWinGravity|
CWBackingStore|CWBackingPlanes|CWBackingPixel|
CWOverrideRedirect|CWSaveUnder|CWEventMask|
CWDontPropagate|CWColormap|CWCursor);
if ((req->mask = valuemask)) {
unsigned long values[32];
register unsigned long *value = values;
unsigned int nvalues;
if (valuemask & CWBackPixmap)
*value++ = attr->background_pixmap;
if (valuemask & CWBackPixel)
*value++ = attr->background_pixel;
if (valuemask & CWBorderPixmap)
*value++ = attr->border_pixmap;
if (valuemask & CWBorderPixel)
*value++ = attr->border_pixel;
if (valuemask & CWBitGravity)
*value++ = attr->bit_gravity;
if (valuemask & CWWinGravity)
*value++ = attr->win_gravity;
if (valuemask & CWBackingStore)
*value++ = attr->backing_store;
if (valuemask & CWBackingPlanes)
*value++ = attr->backing_planes;
if (valuemask & CWBackingPixel)
*value++ = attr->backing_pixel;
if (valuemask & CWOverrideRedirect)
*value++ = attr->override_redirect;
if (valuemask & CWSaveUnder)
*value++ = attr->save_under;
if (valuemask & CWEventMask)
*value++ = attr->event_mask;
if (valuemask & CWDontPropagate)
*value++ = attr->do_not_propagate_mask;
if (valuemask & CWColormap)
*value++ = attr->colormap;
if (valuemask & CWCursor)
*value++ = attr->cursor;
req->length += (nvalues = value - values);
nvalues <<= 2;
Data32 (dpy, (long *) values, (long)nvalues);
}
UnlockDisplay(dpy);
SyncHandle();
return wid;
}
void XmbufClearBufferArea (
Display *dpy,
Multibuffer buffer,
int x, int y,
unsigned int width, unsigned int height,
Bool exposures)
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufClearImageBufferAreaReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufClearImageBufferArea, req, info);
req->buffer = buffer;
req->x = x;
req->y = y;
req->width = width;
req->height = height;
req->exposures = exposures;
UnlockDisplay (dpy);
SyncHandle();
}