Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  *
      3 Copyright 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24  *
     25  * Authors:  Jim Fulton, MIT X Consortium
     26  */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include <config.h>
     30 #endif
     31 #include <X11/Xlibint.h>
     32 #include <stdio.h>
     33 #include <X11/extensions/Xext.h>
     34 #include <X11/extensions/extutil.h>
     35 #include <X11/extensions/multibufproto.h>
     36 #include <X11/extensions/multibuf.h>
     37 
     38 static XExtensionInfo _multibuf_info_data;
     39 static XExtensionInfo *multibuf_info = &_multibuf_info_data;
     40 static const char *multibuf_extension_name = MULTIBUFFER_PROTOCOL_NAME;
     41 
     42 #define MbufCheckExtension(dpy,i,val) \
     43   XextCheckExtension (dpy, i, multibuf_extension_name, val)
     44 #define MbufSimpleCheckExtension(dpy,i) \
     45   XextSimpleCheckExtension (dpy, i, multibuf_extension_name)
     46 
     47 
     48 /*****************************************************************************
     49  *                                                                           *
     50  *			   private utility routines                          *
     51  *                                                                           *
     52  *****************************************************************************/
     53 
     54 /*
     55  * find_display - locate the display info block
     56  */
     57 static int close_display(Display *dpy, XExtCodes *codes);
     58 static char *error_string(Display *dpy, int code, XExtCodes *codes, char *buf, int n);
     59 static Bool wire_to_event(Display *dpy, XEvent *libevent, xEvent *netevent);
     60 static Status event_to_wire(Display *dpy, XEvent *libevent, xEvent *netevent);
     61 static /* const */ XExtensionHooks multibuf_extension_hooks = {
     62     NULL,				/* create_gc */
     63     NULL,				/* copy_gc */
     64     NULL,				/* flush_gc */
     65     NULL,				/* free_gc */
     66     NULL,				/* create_font */
     67     NULL,				/* free_font */
     68     close_display,			/* close_display */
     69     wire_to_event,			/* wire_to_event */
     70     event_to_wire,			/* event_to_wire */
     71     NULL,				/* error */
     72     error_string,			/* error_string */
     73 };
     74 
     75 static const char *multibuf_error_list[] = {
     76     "BadBuffer",			/* MultibufferBadBuffer */
     77 };
     78 
     79 static XEXT_GENERATE_FIND_DISPLAY (find_display, multibuf_info,
     80 				   multibuf_extension_name,
     81 				   &multibuf_extension_hooks,
     82 				   MultibufferNumberEvents, NULL)
     83 
     84 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, multibuf_info)
     85 
     86 static XEXT_GENERATE_ERROR_STRING (error_string, multibuf_extension_name,
     87 				   MultibufferNumberErrors,
     88 				   multibuf_error_list)
     89 
     90 /*
     91  * wire_to_event - convert a wire event in network format to a C
     92  * event structure
     93  */
     94 static Bool wire_to_event (Display *dpy, XEvent *libevent, xEvent *netevent)
     95 {
     96     XExtDisplayInfo *info = find_display (dpy);
     97 
     98     MbufCheckExtension (dpy, info, False);
     99 
    100     switch ((netevent->u.u.type & 0x7f) - info->codes->first_event) {
    101       case MultibufferClobberNotify:
    102 	{
    103 	    XmbufClobberNotifyEvent *ev;
    104 	    xMbufClobberNotifyEvent *event;
    105 
    106     	    ev = (XmbufClobberNotifyEvent *) libevent;
    107 	    event = (xMbufClobberNotifyEvent *) netevent;
    108     	    ev->type = event->type & 0x7f;
    109     	    ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
    110     	    ev->send_event = ((event->type & 0x80) != 0);
    111     	    ev->display = dpy;
    112     	    ev->buffer = event->buffer;
    113 	    ev->state = event->state;
    114     	    return True;
    115 	}
    116       case MultibufferUpdateNotify:
    117 	{
    118 	    XmbufUpdateNotifyEvent *ev;
    119 	    xMbufUpdateNotifyEvent *event;
    120 
    121 	    ev = (XmbufUpdateNotifyEvent *) libevent;
    122 	    event = (xMbufUpdateNotifyEvent *) netevent;
    123 	    ev->type = event->type & 0x7f;
    124 	    ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
    125 	    ev->send_event = ((event->type & 0x80) != 0);
    126 	    ev->display = dpy;
    127 	    ev->buffer = event->buffer;
    128 	    return True;
    129 	}
    130     }
    131     return False;
    132 }
    133 
    134 
    135 /*
    136  * event_to_wire - convert a C event structure to a wire event in
    137  * network format
    138  */
    139 static Status event_to_wire (Display *dpy, XEvent *libevent, xEvent *netevent)
    140 {
    141     XExtDisplayInfo *info = find_display (dpy);
    142 
    143     MbufCheckExtension (dpy, info, 0);
    144 
    145     switch ((libevent->type & 0x7f) - info->codes->first_event) {
    146       case MultibufferClobberNotify:
    147 	{
    148 	    XmbufClobberNotifyEvent *ev;
    149 	    xMbufClobberNotifyEvent *event;
    150 
    151     	    ev = (XmbufClobberNotifyEvent *) libevent;
    152 	    event = (xMbufClobberNotifyEvent *) netevent;
    153     	    event->type = ev->type;
    154     	    event->sequenceNumber = (ev->serial & 0xffff);
    155     	    event->buffer = ev->buffer;
    156 	    event->state = ev->state;
    157     	    return 1;
    158 	}
    159       case MultibufferUpdateNotify:
    160 	{
    161 	    XmbufUpdateNotifyEvent *ev;
    162 	    xMbufUpdateNotifyEvent *event;
    163 
    164 	    ev = (XmbufUpdateNotifyEvent *) libevent;
    165 	    event = (xMbufUpdateNotifyEvent *) netevent;
    166 	    event->type = ev->type;
    167 	    event->sequenceNumber = (ev->serial & 0xffff);
    168 	    event->buffer = ev->buffer;
    169 	    return 1;
    170 	}
    171     }
    172     return 0;
    173 }
    174 
    175 
    176 /*
    177  * read_buffer_info - read Buffer Info descriptors from the net; if unable
    178  * to allocate memory, read junk to make sure that stream is clear.
    179  */
    180 #define TALLOC(type,count) Xcalloc ((unsigned) count, sizeof(type))
    181 
    182 static XmbufBufferInfo *read_buffer_info (Display *dpy, int nbufs)
    183 {
    184     xMbufBufferInfo *netbuf = TALLOC (xMbufBufferInfo, nbufs);
    185     XmbufBufferInfo *bufinfo = NULL;
    186     long netbytes = nbufs * SIZEOF(xMbufBufferInfo);
    187 
    188     if (netbuf) {
    189 	_XRead (dpy, (char *) netbuf, netbytes);
    190 
    191 	bufinfo = TALLOC (XmbufBufferInfo, nbufs);
    192 	if (bufinfo) {
    193 	    register XmbufBufferInfo *c;
    194 	    register xMbufBufferInfo *net;
    195 	    register int i;
    196 
    197 	    for (i = 0, c = bufinfo, net = netbuf; i < nbufs;
    198 		 i++, c++, net++) {
    199 		c->visualid = net->visualID;
    200 		c->max_buffers = net->maxBuffers;
    201 		c->depth = net->depth;
    202 	    }
    203 	}
    204 	Xfree (netbuf);
    205     } else {				/* eat the data */
    206 	while (netbytes > 0) {
    207 	    char dummy[256];		/* stack size vs loops tradeoff */
    208 	    long nbytes = sizeof dummy;
    209 
    210 	    if (nbytes > netbytes) nbytes = netbytes;
    211 	    _XRead (dpy, dummy, nbytes);
    212 	    netbytes -= nbytes;
    213 	}
    214     }
    215 
    216     return bufinfo;
    217 }
    218 
    219 #undef TALLOC
    220 
    221 
    222 /*****************************************************************************
    223  *                                                                           *
    224  *		    Multibuffering/stereo public interfaces                  *
    225  *                                                                           *
    226  *****************************************************************************/
    227 
    228 
    229 /*
    230  * XmbufQueryExtension -
    231  * 	Returns True if the multibuffering/stereo extension is available
    232  * 	on the given display.  If the extension exists, the value of the
    233  * 	first event code (which should be added to the event type constants
    234  * 	MultibufferClobberNotify and MultibufferUpdateNotify to get the
    235  * 	actual values) is stored into event_base and the value of the first
    236  * 	error code (which should be added to the error type constant
    237  * 	MultibufferBadBuffer to get the actual value) is stored into
    238  * 	error_base.
    239  */
    240 Bool XmbufQueryExtension (
    241     Display *dpy,
    242     int *event_base_return, int *error_base_return)
    243 {
    244     XExtDisplayInfo *info = find_display (dpy);
    245 
    246     if (XextHasExtension (info)) {
    247 	*event_base_return = info->codes->first_event;
    248 	*error_base_return = info->codes->first_error;
    249 	return True;
    250     } else {
    251 	return False;
    252     }
    253 }
    254 
    255 
    256 /*
    257  * XmbufGetVersion -
    258  * 	Gets the major and minor version numbers of the extension.  The return
    259  * 	value is zero if an error occurs or non-zero if no error happens.
    260  */
    261 Status XmbufGetVersion (
    262     Display *dpy,
    263     int *major_version_return, int *minor_version_return)
    264 {
    265     XExtDisplayInfo *info = find_display (dpy);
    266     xMbufGetBufferVersionReply rep;
    267     register xMbufGetBufferVersionReq *req;
    268 
    269     MbufCheckExtension (dpy, info, 0);
    270 
    271     LockDisplay (dpy);
    272     MbufGetReq (MbufGetBufferVersion, req, info);
    273     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
    274 	UnlockDisplay (dpy);
    275 	SyncHandle ();
    276 	return 0;
    277     }
    278     *major_version_return = rep.majorVersion;
    279     *minor_version_return = rep.minorVersion;
    280     UnlockDisplay (dpy);
    281 
    282     SyncHandle ();
    283     return 1;
    284 }
    285 
    286 
    287 /*
    288  * XmbufCreateBuffers -
    289  * 	Requests that "count" buffers be created with the given update_action
    290  * 	and update_hint and be associated with the indicated window.  The
    291  * 	number of buffers created is returned (zero if an error occurred)
    292  * 	and buffers_return is filled in with that many Multibuffer identifiers.
    293  */
    294 int XmbufCreateBuffers (
    295     Display *dpy,
    296     Window w,
    297     int count,
    298     int update_action, int update_hint,
    299     Multibuffer *buffers)
    300 {
    301     XExtDisplayInfo *info = find_display (dpy);
    302     xMbufCreateImageBuffersReply rep;
    303     register xMbufCreateImageBuffersReq *req;
    304     int result;
    305 
    306     MbufCheckExtension (dpy, info, 0);
    307 
    308     LockDisplay (dpy);
    309 
    310     XAllocIDs(dpy, buffers, count);
    311     MbufGetReq (MbufCreateImageBuffers, req, info);
    312     req->window = w;
    313     req->updateAction = update_action;
    314     req->updateHint = update_hint;
    315     req->length += count;
    316     count <<= 2;
    317     PackData32 (dpy, buffers, count);
    318     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
    319 	UnlockDisplay (dpy);
    320 	SyncHandle ();
    321 	return 0;
    322     }
    323     result = rep.numberBuffer;
    324     UnlockDisplay (dpy);
    325 
    326     SyncHandle ();
    327     return result;
    328 }
    329 
    330 
    331 /*
    332  * XmbufDestroyBuffers -
    333  * 	Destroys the buffers associated with the given window.
    334  */
    335 void XmbufDestroyBuffers (Display *dpy, Window window)
    336 {
    337     XExtDisplayInfo *info = find_display (dpy);
    338     register xMbufDestroyImageBuffersReq *req;
    339 
    340     MbufSimpleCheckExtension (dpy, info);
    341 
    342     LockDisplay (dpy);
    343     MbufGetReq (MbufDestroyImageBuffers, req, info);
    344     req->window = window;
    345     UnlockDisplay (dpy);
    346     SyncHandle ();
    347 }
    348 
    349 
    350 /*
    351  * XmbufDisplayBuffers -
    352  * 	Displays the indicated buffers their appropriate windows within
    353  * 	max_delay milliseconds after min_delay milliseconds have passed.
    354  * 	No two buffers may be associated with the same window or else a Match
    355  * 	error is generated.
    356  */
    357 void XmbufDisplayBuffers (
    358     Display *dpy,
    359     int count,
    360     Multibuffer *buffers,
    361     int min_delay, int max_delay)
    362 {
    363     XExtDisplayInfo *info = find_display (dpy);
    364     register xMbufDisplayImageBuffersReq *req;
    365 
    366     MbufSimpleCheckExtension (dpy, info);
    367 
    368     LockDisplay (dpy);
    369     MbufGetReq (MbufDisplayImageBuffers, req, info);
    370     req->minDelay = min_delay;
    371     req->maxDelay = max_delay;
    372     req->length += count;
    373     count <<= 2;
    374     PackData32 (dpy, buffers, count);
    375     UnlockDisplay (dpy);
    376     SyncHandle();
    377 }
    378 
    379 
    380 /*
    381  * XmbufGetWindowAttributes -
    382  * 	Gets the multibuffering attributes that apply to all buffers associated
    383  * 	with the given window.  Returns non-zero on success and zero if an
    384  * 	error occurs.
    385  */
    386 Status XmbufGetWindowAttributes (
    387     Display *dpy,
    388     Window w,
    389     XmbufWindowAttributes *attr)
    390 {
    391     XExtDisplayInfo *info = find_display (dpy);
    392     register xMbufGetMBufferAttributesReq *req;
    393     xMbufGetMBufferAttributesReply rep;
    394 
    395     MbufCheckExtension (dpy, info, 0);
    396 
    397     LockDisplay (dpy);
    398     MbufGetReq (MbufGetMBufferAttributes, req, info);
    399     req->window = w;
    400     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
    401 	UnlockDisplay (dpy);
    402 	SyncHandle ();
    403 	return 0;
    404     }
    405     attr->buffers = (Multibuffer *) NULL;
    406     if ((attr->nbuffers = rep.length)) {
    407 	int nbytes = rep.length * sizeof(Multibuffer);
    408 	attr->buffers = Xmalloc((unsigned) nbytes);
    409 	nbytes = rep.length << 2;
    410 	if (! attr->buffers) {
    411 	    _XEatDataWords(dpy, rep.length);
    412 	    UnlockDisplay(dpy);
    413 	    SyncHandle();
    414 	    return (0);
    415 	}
    416 	_XRead32 (dpy, (long *) attr->buffers, nbytes);
    417     }
    418     attr->displayed_index = rep.displayedBuffer;
    419     attr->update_action = rep.updateAction;
    420     attr->update_hint = rep.updateHint;
    421     attr->window_mode = rep.windowMode;
    422 
    423     UnlockDisplay (dpy);
    424     SyncHandle();
    425     return 1;
    426 }
    427 
    428 
    429 /*
    430  * XmbufChangeWindowAttributes -
    431  * 	Sets the multibuffering attributes that apply to all buffers associated
    432  * 	with the given window.  This is currently limited to the update_hint.
    433  */
    434 void XmbufChangeWindowAttributes (
    435     Display *dpy,
    436     Window w,
    437     unsigned long valuemask,
    438     XmbufSetWindowAttributes *attr)
    439 {
    440     XExtDisplayInfo *info = find_display (dpy);
    441     register xMbufSetMBufferAttributesReq *req;
    442 
    443     MbufSimpleCheckExtension (dpy, info);
    444 
    445     LockDisplay (dpy);
    446     MbufGetReq (MbufSetMBufferAttributes, req, info);
    447     req->window = w;
    448     if ((req->valueMask = valuemask)) {	/* stolen from lib/X/XWindow.c */
    449 	unsigned long values[1];	/* one per element in if stmts below */
    450 	unsigned long *v = values;
    451 	unsigned int nvalues;
    452 
    453 	if (valuemask & MultibufferWindowUpdateHint)
    454 	  *v++ = attr->update_hint;
    455 	req->length += (nvalues = v - values);
    456 	nvalues <<= 2;			/* watch out for macros... */
    457 	Data32 (dpy, (long *) values, (long)nvalues);
    458     }
    459     UnlockDisplay (dpy);
    460     SyncHandle();
    461 }
    462 
    463 
    464 /*
    465  * XmbufGetBufferAttributes -
    466  * 	Gets the attributes for the indicated buffer.  Returns non-zero on
    467  * 	success and zero if an error occurs.
    468  */
    469 Status XmbufGetBufferAttributes (
    470     Display *dpy,
    471     Multibuffer b,
    472     XmbufBufferAttributes *attr)
    473 {
    474     XExtDisplayInfo *info = find_display (dpy);
    475     register xMbufGetBufferAttributesReq *req;
    476     xMbufGetBufferAttributesReply rep;
    477 
    478     MbufCheckExtension (dpy, info, 0);
    479 
    480     LockDisplay (dpy);
    481     MbufGetReq (MbufGetBufferAttributes, req, info);
    482     req->buffer = b;
    483     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
    484 	UnlockDisplay (dpy);
    485 	SyncHandle ();
    486 	return 0;
    487     }
    488     attr->window = rep.window;
    489     attr->event_mask = rep.eventMask;
    490     attr->buffer_index = rep.bufferIndex;
    491     attr->side = rep.side;
    492 
    493     UnlockDisplay (dpy);
    494     SyncHandle();
    495     return 1;
    496 }
    497 
    498 
    499 /*
    500  * XmbufChangeBufferAttributes -
    501  * 	Sets the attributes for the indicated buffer.  This is currently
    502  * 	limited to the event_mask.
    503  */
    504 void XmbufChangeBufferAttributes (
    505     Display *dpy,
    506     Multibuffer b,
    507     unsigned long valuemask,
    508     XmbufSetBufferAttributes *attr)
    509 {
    510     XExtDisplayInfo *info = find_display (dpy);
    511     register xMbufSetBufferAttributesReq *req;
    512 
    513     MbufSimpleCheckExtension (dpy, info);
    514 
    515     LockDisplay (dpy);
    516     MbufGetReq (MbufSetBufferAttributes, req, info);
    517     req->buffer = b;
    518     if ((req->valueMask = valuemask)) {	/* stolen from lib/X/XWindow.c */
    519 	unsigned long values[1];	/* one per element in if stmts below */
    520 	unsigned long *v = values;
    521 	unsigned int nvalues;
    522 
    523 	if (valuemask & MultibufferBufferEventMask)
    524 	  *v++ = attr->event_mask;
    525 	req->length += (nvalues = v - values);
    526 	nvalues <<= 2;			/* watch out for macros... */
    527 	Data32 (dpy, (long *) values, (long)nvalues);
    528     }
    529     UnlockDisplay (dpy);
    530     SyncHandle();
    531 }
    532 
    533 
    534 
    535 /*
    536  * XmbufGetScreenInfo -
    537  * 	Gets the parameters controlling how mono and stereo windows may be
    538  * 	created on the indicated screen.  The numbers of sets of visual and
    539  * 	depths are returned in nmono_return and nstereo_return.  If
    540  * 	nmono_return is greater than zero, then mono_info_return is set to
    541  * 	the address of an array of XmbufBufferInfo structures describing the
    542  * 	various visuals and depths that may be used.  Otherwise,
    543  * 	mono_info_return is set to NULL.  Similarly, stereo_info_return is
    544  * 	set according to nstereo_return.  The storage returned in
    545  * 	mono_info_return and stereo_info_return may be released by XFree.
    546  * 	If no errors are encountered, non-zero will be returned.
    547  */
    548 Status XmbufGetScreenInfo (
    549     Display *dpy,
    550     Drawable d,
    551     int *nmono_return,
    552     XmbufBufferInfo **mono_info_return,
    553     int *nstereo_return,
    554     XmbufBufferInfo **stereo_info_return)
    555 {
    556     XExtDisplayInfo *info = find_display (dpy);
    557     register xMbufGetBufferInfoReq *req;
    558     xMbufGetBufferInfoReply rep;
    559     int nmono, nstereo;
    560     XmbufBufferInfo *minfo, *sinfo;
    561 
    562     MbufCheckExtension (dpy, info, 0);
    563 
    564     LockDisplay (dpy);
    565     MbufGetReq (MbufGetBufferInfo, req, info);
    566     req->drawable = d;
    567     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
    568 	UnlockDisplay (dpy);
    569 	SyncHandle ();
    570 	return 0;
    571     }
    572     nmono = rep.normalInfo;
    573     nstereo = rep.stereoInfo;
    574     minfo = ((nmono > 0) ? read_buffer_info (dpy, nmono) : NULL);
    575     sinfo = ((nstereo > 0) ? read_buffer_info (dpy, nstereo) : NULL);
    576 
    577     /* check for bad reads indicating we need to return an error */
    578     if ((nmono > 0 && !minfo) || (nstereo > 0 && !sinfo)) {
    579 	if (minfo) Xfree (minfo);
    580 	if (sinfo) Xfree (sinfo);
    581 	UnlockDisplay (dpy);
    582 	SyncHandle();
    583 	return 0;
    584     }
    585 
    586     *nmono_return = nmono;
    587     *mono_info_return = minfo;
    588     *nstereo_return = nstereo;
    589     *stereo_info_return = sinfo;
    590 
    591     UnlockDisplay (dpy);
    592     SyncHandle();
    593     return 1;
    594 }
    595 
    596 
    597 /*
    598  * XmbufCreateStereoWindow -
    599  * 	Creates a stereo window in the same way that XCreateWindow creates
    600  * 	a mono window (in fact, use the same code, except for the request)
    601  *      and returns the left and right buffers that may be
    602  */
    603 Window XmbufCreateStereoWindow (
    604     Display *dpy,
    605     Window parent,
    606     int x, int y,
    607     unsigned int width, unsigned int height, unsigned int border_width,
    608     int depth,
    609     unsigned int class,
    610     Visual *visual,
    611     unsigned long valuemask,
    612     XSetWindowAttributes *attr,
    613     Multibuffer *leftp, Multibuffer *rightp)
    614 {
    615     XExtDisplayInfo *info = find_display (dpy);
    616     Window wid;
    617     register xMbufCreateStereoWindowReq *req;
    618 
    619     MbufCheckExtension (dpy, info, None);
    620 
    621     LockDisplay(dpy);
    622     MbufGetReq(MbufCreateStereoWindow, req, info);
    623     wid = req->wid = XAllocID(dpy);
    624     req->parent = parent;
    625     req->left = *leftp = XAllocID (dpy);
    626     req->right = *rightp = XAllocID (dpy);
    627     req->x = x;
    628     req->y = y;
    629     req->width = width;
    630     req->height = height;
    631     req->borderWidth = border_width;
    632     req->depth = depth;
    633     req->class = class;
    634     if (visual == (Visual *)CopyFromParent)
    635 	req->visual = CopyFromParent;
    636     else
    637 	req->visual = visual->visualid;
    638     valuemask &= (CWBackPixmap|CWBackPixel|CWBorderPixmap|
    639 		     CWBorderPixel|CWBitGravity|CWWinGravity|
    640 		     CWBackingStore|CWBackingPlanes|CWBackingPixel|
    641 		     CWOverrideRedirect|CWSaveUnder|CWEventMask|
    642 		     CWDontPropagate|CWColormap|CWCursor);
    643     if ((req->mask = valuemask)) {
    644 	unsigned long values[32];
    645 	register unsigned long *value = values;
    646 	unsigned int nvalues;
    647 
    648 	if (valuemask & CWBackPixmap)
    649 	  *value++ = attr->background_pixmap;
    650 	if (valuemask & CWBackPixel)
    651 	  *value++ = attr->background_pixel;
    652 	if (valuemask & CWBorderPixmap)
    653 	  *value++ = attr->border_pixmap;
    654 	if (valuemask & CWBorderPixel)
    655 	  *value++ = attr->border_pixel;
    656 	if (valuemask & CWBitGravity)
    657 	  *value++ = attr->bit_gravity;
    658 	if (valuemask & CWWinGravity)
    659 	  *value++ = attr->win_gravity;
    660 	if (valuemask & CWBackingStore)
    661 	  *value++ = attr->backing_store;
    662 	if (valuemask & CWBackingPlanes)
    663 	  *value++ = attr->backing_planes;
    664 	if (valuemask & CWBackingPixel)
    665 	  *value++ = attr->backing_pixel;
    666 	if (valuemask & CWOverrideRedirect)
    667 	  *value++ = attr->override_redirect;
    668 	if (valuemask & CWSaveUnder)
    669 	  *value++ = attr->save_under;
    670 	if (valuemask & CWEventMask)
    671 	  *value++ = attr->event_mask;
    672 	if (valuemask & CWDontPropagate)
    673 	  *value++ = attr->do_not_propagate_mask;
    674 	if (valuemask & CWColormap)
    675 	  *value++ = attr->colormap;
    676 	if (valuemask & CWCursor)
    677 	  *value++ = attr->cursor;
    678 	req->length += (nvalues = value - values);
    679 
    680 	nvalues <<= 2;			    /* watch out for macros... */
    681 	Data32 (dpy, (long *) values, (long)nvalues);
    682     }
    683     UnlockDisplay(dpy);
    684     SyncHandle();
    685     return wid;
    686 }
    687 
    688 void XmbufClearBufferArea (
    689     Display *dpy,
    690     Multibuffer buffer,
    691     int x, int y,
    692     unsigned int width, unsigned int height,
    693     Bool exposures)
    694 {
    695     XExtDisplayInfo *info = find_display (dpy);
    696     register xMbufClearImageBufferAreaReq *req;
    697 
    698     MbufSimpleCheckExtension (dpy, info);
    699 
    700     LockDisplay (dpy);
    701     MbufGetReq (MbufClearImageBufferArea, req, info);
    702     req->buffer = buffer;
    703     req->x      = x;
    704     req->y      = y;
    705     req->width  = width;
    706     req->height = height;
    707     req->exposures = exposures;
    708     UnlockDisplay (dpy);
    709     SyncHandle();
    710 }
    711 
    712