home *** CD-ROM | disk | FTP | other *** search
- /*
- * $XConsortium: XMultibuf.c,v 1.26 91/05/04 19:32:35 rws Exp $
- *
- * Copyright 1989 Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of M.I.T. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. M.I.T. makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors: Jim Fulton, MIT X Consortium
- */
-
- #define NEED_EVENTS
- #define NEED_REPLIES
- #include <X11/Xlibint.h>
- #include "Xext.h" /* in ../include */
- #include "extutil.h" /* in ../include */
- #include "multibufst.h" /* in ../include */
-
- static XExtensionInfo _multibuf_info_data;
- static XExtensionInfo *multibuf_info = &_multibuf_info_data;
- static /* const */ 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)
-
-
- /*****************************************************************************
- * *
- * private utility routines *
- * *
- *****************************************************************************/
-
- /*
- * find_display - locate the display info block
- */
- static int close_display();
- static char *error_string();
- static Bool wire_to_event();
- static Status event_to_wire();
- static /* const */ XExtensionHooks multibuf_extension_hooks = {
- NULL, /* create_gc */
- NULL, /* copy_gc */
- NULL, /* flush_gc */
- NULL, /* free_gc */
- NULL, /* create_font */
- NULL, /* free_font */
- close_display, /* close_display */
- wire_to_event, /* wire_to_event */
- event_to_wire, /* event_to_wire */
- NULL, /* error */
- error_string, /* error_string */
- };
-
- static /* const */ char *multibuf_error_list[] = {
- "BadBuffer", /* MultibufferBadBuffer */
- };
-
- 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)
-
- /*
- * wire_to_event - convert a wire event in network format to a C
- * event structure
- */
- static Bool wire_to_event (dpy, libevent, netevent)
- 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;
- 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;
- }
-
-
- /*
- * event_to_wire - convert a C event structure to a wire event in
- * network format
- */
- static Status event_to_wire (dpy, libevent, netevent)
- 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;
- 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;
- }
-
-
- /*
- * read_buffer_info - read Buffer Info descriptors from the net; if unable
- * to allocate memory, read junk to make sure that stream is clear.
- */
- #define TALLOC(type,count) ((type *) Xmalloc ((unsigned) count * sizeof(type)))
-
- static XmbufBufferInfo *read_buffer_info (dpy, nbufs)
- 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 { /* eat the data */
- while (netbytes > 0) {
- char dummy[256]; /* stack size vs loops tradeoff */
- long nbytes = sizeof dummy;
-
- if (nbytes > netbytes) nbytes = netbytes;
- _XRead (dpy, dummy, nbytes);
- netbytes -= nbytes;
- }
- }
-
- return bufinfo;
- }
-
- #undef TALLOC
-
-
- /*****************************************************************************
- * *
- * Multibuffering/stereo public interfaces *
- * *
- *****************************************************************************/
-
-
- /*
- * XmbufQueryExtension -
- * Returns True if the multibuffering/stereo extension is available
- * on the given display. If the extension exists, the value of the
- * first event code (which should be added to the event type constants
- * MultibufferClobberNotify and MultibufferUpdateNotify to get the
- * actual values) is stored into event_base and the value of the first
- * error code (which should be added to the error type constant
- * MultibufferBadBuffer to get the actual value) is stored into
- * error_base.
- */
- Bool XmbufQueryExtension (dpy, event_base_return, error_base_return)
- Display *dpy;
- int *event_base_return, *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;
- }
- }
-
-
- /*
- * XmbufGetVersion -
- * Gets the major and minor version numbers of the extension. The return
- * value is zero if an error occurs or non-zero if no error happens.
- */
- Status XmbufGetVersion (dpy, major_version_return, minor_version_return)
- Display *dpy;
- int *major_version_return, *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;
- }
-
-
- /*
- * XmbufCreateBuffers -
- * Requests that "count" buffers be created with the given update_action
- * and update_hint and be associated with the indicated window. The
- * number of buffers created is returned (zero if an error occurred)
- * and buffers_return is filled in with that many Multibuffer identifiers.
- */
- int XmbufCreateBuffers (dpy, w, count, update_action, update_hint, buffers)
- Display *dpy;
- Window w;
- int count;
- int update_action, update_hint;
- Multibuffer *buffers;
- {
- XExtDisplayInfo *info = find_display (dpy);
- xMbufCreateImageBuffersReply rep;
- register xMbufCreateImageBuffersReq *req;
- int i, result;
-
- MbufCheckExtension (dpy, info, 0);
-
- /*
- * allocate the id; hopefully, it would be nice to be able to
- * get rid of the ones we don't need, but this would require access
- * various Xlib internals. we could do caching on this side, but the
- * chances of wasting enough resources to really matter is very small
- */
- for (i = 0; i < count; i++) buffers[i] = XAllocID (dpy);
-
- LockDisplay (dpy);
- MbufGetReq (MbufCreateImageBuffers, req, info);
- req->window = w;
- req->updateAction = update_action;
- req->updateHint = update_hint;
- req->length += count;
- PackData32 (dpy, buffers, count * sizeof (Multibuffer));
- if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
- UnlockDisplay (dpy);
- SyncHandle ();
- return 0;
- }
- result = rep.numberBuffer;
- UnlockDisplay (dpy);
-
- SyncHandle ();
- return result;
- }
-
-
- /*
- * XmbufDestroyBuffers -
- * Destroys the buffers associated with the given window.
- */
- void XmbufDestroyBuffers (dpy, window)
- 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 ();
- }
-
-
- /*
- * XmbufDisplayBuffers -
- * Displays the indicated buffers their appropriate windows within
- * max_delay milliseconds after min_delay milliseconds have passed.
- * No two buffers may be associated with the same window or else a Matc
- * error is generated.
- */
- void XmbufDisplayBuffers (dpy, count, buffers, min_delay, max_delay)
- Display *dpy;
- int count;
- Multibuffer *buffers;
- int min_delay, 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;
- PackData32 (dpy, buffers, count * sizeof (Multibuffer));
- UnlockDisplay (dpy);
- SyncHandle();
- }
-
-
- /*
- * XmbufGetWindowAttributes -
- * Gets the multibuffering attributes that apply to all buffers associated
- * with the given window. Returns non-zero on success and zero if an
- * error occurs.
- */
- Status XmbufGetWindowAttributes (dpy, w, attr)
- 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, (char *) 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;
- }
-
-
- /*
- * XmbufChangeWindowAttributes -
- * Sets the multibuffering attributes that apply to all buffers associated
- * with the given window. This is currently limited to the update_hint.
- */
- void XmbufChangeWindowAttributes (dpy, w, valuemask, attr)
- 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) { /* stolen from lib/X/XWindow.c */
- unsigned long values[1]; /* one per element in if stmts below */
- unsigned long *v = values;
- unsigned int nvalues;
-
- if (valuemask & MultibufferWindowUpdateHint)
- *v++ = attr->update_hint;
- req->length += (nvalues = v - values);
- nvalues <<= 2; /* watch out for macros... */
- Data32 (dpy, (long *) values, (long)nvalues);
- }
- UnlockDisplay (dpy);
- SyncHandle();
- }
-
-
- /*
- * XmbufGetBufferAttributes -
- * Gets the attributes for the indicated buffer. Returns non-zero on
- * success and zero if an error occurs.
- */
- Status XmbufGetBufferAttributes (dpy, b, attr)
- 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;
- }
-
-
- /*
- * XmbufChangeBufferAttributes -
- * Sets the attributes for the indicated buffer. This is currently
- * limited to the event_mask.
- */
- void XmbufChangeBufferAttributes (dpy, b, valuemask, attr)
- 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) { /* stolen from lib/X/XWindow.c */
- unsigned long values[1]; /* one per element in if stmts below */
- unsigned long *v = values;
- unsigned int nvalues;
-
- if (valuemask & MultibufferBufferEventMask)
- *v++ = attr->event_mask;
- req->length += (nvalues = v - values);
- nvalues <<= 2; /* watch out for macros... */
- Data32 (dpy, (long *) values, (long)nvalues);
- }
- UnlockDisplay (dpy);
- SyncHandle();
- }
-
-
-
- /*
- * XmbufGetScreenInfo -
- * Gets the parameters controlling how mono and stereo windows may be
- * created on the indicated screen. The numbers of sets of visual and
- * depths are returned in nmono_return and nstereo_return. If
- * nmono_return is greater than zero, then mono_info_return is set to
- * the address of an array of XmbufBufferInfo structures describing the
- * various visuals and depths that may be used. Otherwise,
- * mono_info_return is set to NULL. Similarly, stereo_info_return is
- * set according to nstereo_return. The storage returned in
- * mono_info_return and stereo_info_return may be released by XFree.
- * If no errors are encounted, non-zero will be returned.
- */
- Status XmbufGetScreenInfo (dpy, d, nmono_return, mono_info_return,
- nstereo_return, stereo_info_return)
- 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);
-
- /* check for bad reads indicating we need to return an error */
- 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;
- }
-
-
- /*
- * XmbufCreateStereoWindow -
- * Creates a stereo window in the same way that XCreateWindow creates
- * a mono window (in fact, use the same code, except for the request)
- * and returns the left and right buffers that may be
- */
- Window XmbufCreateStereoWindow (dpy, parent, x, y, width, height, border_width,
- depth, class, visual, valuemask, attr,
- leftp, rightp)
- Display *dpy;
- Window parent;
- int x, y;
- unsigned int width, height, border_width;
- int depth;
- unsigned int class;
- Visual *visual;
- unsigned long valuemask;
- XSetWindowAttributes *attr;
- Multibuffer *leftp, *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; /* watch out for macros... */
- Data32 (dpy, (long *) values, (long)nvalues);
- }
- UnlockDisplay(dpy);
- SyncHandle();
- return wid;
- }
-
-