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  * Author:  Keith Packard, MIT X Consortium
     26  */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include <config.h>
     30 #endif
     31 #include <X11/Xlibint.h>
     32 #include <X11/Xutil.h>
     33 #include <X11/Xregion.h>
     34 #include <X11/extensions/Xext.h>
     35 #include <X11/extensions/extutil.h>
     36 #include <X11/extensions/shape.h>
     37 #include <X11/extensions/shapeproto.h>
     38 #include <limits.h>
     39 #include "reallocarray.h"
     40 
     41 static XExtensionInfo _shape_info_data;
     42 static XExtensionInfo *shape_info = &_shape_info_data;
     43 static const char *shape_extension_name = SHAPENAME;
     44 
     45 #define ShapeCheckExtension(dpy,i,val) \
     46   XextCheckExtension (dpy, i, shape_extension_name, val)
     47 #define ShapeSimpleCheckExtension(dpy,i) \
     48   XextSimpleCheckExtension (dpy, i, shape_extension_name)
     49 
     50 
     51 /*****************************************************************************
     52  *                                                                           *
     53  *			   private utility routines                          *
     54  *                                                                           *
     55  *****************************************************************************/
     56 
     57 static int close_display(Display *dpy, XExtCodes *codes);
     58 static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
     59 static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
     60 static /* const */ XExtensionHooks shape_extension_hooks = {
     61     NULL,				/* create_gc */
     62     NULL,				/* copy_gc */
     63     NULL,				/* flush_gc */
     64     NULL,				/* free_gc */
     65     NULL,				/* create_font */
     66     NULL,				/* free_font */
     67     close_display,			/* close_display */
     68     wire_to_event,			/* wire_to_event */
     69     event_to_wire,			/* event_to_wire */
     70     NULL,				/* error */
     71     NULL,				/* error_string */
     72 };
     73 
     74 static XEXT_GENERATE_FIND_DISPLAY (find_display, shape_info,
     75 				   shape_extension_name,
     76 				   &shape_extension_hooks,
     77 				   ShapeNumberEvents, NULL)
     78 
     79 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shape_info)
     80 
     81 
     82 static Bool
     83 wire_to_event (Display *dpy, XEvent *re, xEvent *event)
     84 {
     85     XExtDisplayInfo *info = find_display (dpy);
     86     XShapeEvent		*se;
     87     xShapeNotifyEvent	*sevent;
     88 
     89     ShapeCheckExtension (dpy, info, False);
     90 
     91     switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
     92     case ShapeNotify:
     93     	se = (XShapeEvent *) re;
     94 	sevent = (xShapeNotifyEvent *) event;
     95     	se->type = sevent->type & 0x7f;
     96     	se->serial = _XSetLastRequestRead(dpy,(xGenericReply *) event);
     97     	se->send_event = (sevent->type & 0x80) != 0;
     98     	se->display = dpy;
     99     	se->window = sevent->window;
    100     	se->kind = sevent->kind;
    101     	se->x = cvtINT16toInt (sevent->x);
    102     	se->y = cvtINT16toInt (sevent->y);
    103     	se->width = sevent->width;
    104     	se->height = sevent->height;
    105 	se->time = sevent->time;
    106 	se->shaped = True;
    107 	if (sevent->shaped == xFalse)
    108 	    se->shaped = False;
    109     	return True;
    110     }
    111     return False;
    112 }
    113 
    114 static Status
    115 event_to_wire (Display *dpy, XEvent *re, xEvent *event)
    116 {
    117     XExtDisplayInfo *info = find_display (dpy);
    118     XShapeEvent		*se;
    119     xShapeNotifyEvent	*sevent;
    120 
    121     ShapeCheckExtension (dpy, info, 0);
    122 
    123     switch ((re->type & 0x7f) - info->codes->first_event) {
    124     case ShapeNotify:
    125     	se = (XShapeEvent *) re;
    126 	sevent = (xShapeNotifyEvent *) event;
    127     	sevent->type = se->type | (se->send_event ? 0x80 : 0);
    128     	sevent->sequenceNumber = se->serial & 0xffff;
    129     	sevent->window = se->window;
    130     	sevent->kind = se->kind;
    131     	sevent->x = se->x;
    132     	sevent->y = se->y;
    133     	sevent->width = se->width;
    134     	sevent->height = se->height;
    135 	sevent->time = se->time;
    136     	return 1;
    137     }
    138     return 0;
    139 }
    140 
    141 
    142 /****************************************************************************
    143  *                                                                          *
    144  *			    Shape public interfaces                         *
    145  *                                                                          *
    146  ****************************************************************************/
    147 
    148 Bool XShapeQueryExtension (Display *dpy, int *event_basep, int *error_basep)
    149 {
    150     XExtDisplayInfo *info = find_display (dpy);
    151 
    152     if (XextHasExtension(info)) {
    153 	*event_basep = info->codes->first_event;
    154 	*error_basep = info->codes->first_error;
    155 	return True;
    156     } else {
    157 	return False;
    158     }
    159 }
    160 
    161 
    162 Status XShapeQueryVersion(
    163     Display *dpy,
    164     int *major_versionp,
    165     int *minor_versionp)
    166 {
    167     XExtDisplayInfo *info = find_display (dpy);
    168     xShapeQueryVersionReply	    rep;
    169     register xShapeQueryVersionReq  *req;
    170 
    171     ShapeCheckExtension (dpy, info, 0);
    172 
    173     LockDisplay (dpy);
    174     GetReq (ShapeQueryVersion, req);
    175     req->reqType = info->codes->major_opcode;
    176     req->shapeReqType = X_ShapeQueryVersion;
    177     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
    178 	UnlockDisplay (dpy);
    179 	SyncHandle ();
    180 	return 0;
    181     }
    182     *major_versionp = rep.majorVersion;
    183     *minor_versionp = rep.minorVersion;
    184     UnlockDisplay (dpy);
    185     SyncHandle ();
    186     return 1;
    187 }
    188 
    189 void XShapeCombineRegion(
    190     register Display *dpy,
    191     Window dest,
    192     int destKind, int xOff, int yOff,
    193     register REGION *r,
    194     int op)
    195 {
    196     XExtDisplayInfo *info = find_display (dpy);
    197     register xShapeRectanglesReq *req;
    198     register long nbytes;
    199     register int i;
    200     register XRectangle *xr, *pr;
    201     register BOX *pb;
    202 
    203     ShapeSimpleCheckExtension (dpy, info);
    204 
    205     LockDisplay(dpy);
    206     GetReq(ShapeRectangles, req);
    207     xr = (XRectangle *)
    208     	_XAllocScratch(dpy, (unsigned long)(r->numRects * sizeof (XRectangle)));
    209     for (pr = xr, pb = r->rects, i = r->numRects; --i >= 0; pr++, pb++) {
    210         pr->x = pb->x1;
    211 	pr->y = pb->y1;
    212 	pr->width = pb->x2 - pb->x1;
    213 	pr->height = pb->y2 - pb->y1;
    214      }
    215     req->reqType = info->codes->major_opcode;
    216     req->shapeReqType = X_ShapeRectangles;
    217     req->op = op;
    218     req->ordering = YXBanded;
    219     req->destKind = destKind;
    220     req->dest = dest;
    221     req->xOff = xOff;
    222     req->yOff = yOff;
    223 
    224     /* SIZEOF(xRectangle) will be a multiple of 4 */
    225     req->length += r->numRects * (SIZEOF(xRectangle) / 4);
    226 
    227     nbytes = r->numRects * sizeof(xRectangle);
    228 
    229     Data16 (dpy, (short *) xr, nbytes);
    230     UnlockDisplay(dpy);
    231     SyncHandle();
    232 }
    233 
    234 
    235 void XShapeCombineRectangles (
    236     register Display *dpy,
    237     XID dest,
    238     int destKind, int xOff, int yOff,
    239     XRectangle *rects,
    240     int n_rects,
    241     int op, int ordering)
    242 {
    243     XExtDisplayInfo *info = find_display (dpy);
    244     register xShapeRectanglesReq *req;
    245     register long nbytes;
    246 
    247     ShapeSimpleCheckExtension (dpy, info);
    248 
    249     LockDisplay(dpy);
    250     GetReq(ShapeRectangles, req);
    251     req->reqType = info->codes->major_opcode;
    252     req->shapeReqType = X_ShapeRectangles;
    253     req->op = op;
    254     req->ordering = ordering;
    255     req->destKind = destKind;
    256     req->dest = dest;
    257     req->xOff = xOff;
    258     req->yOff = yOff;
    259 
    260     /* SIZEOF(xRectangle) will be a multiple of 4 */
    261     req->length += n_rects * (SIZEOF(xRectangle) / 4);
    262 
    263     nbytes = n_rects * sizeof(xRectangle);
    264 
    265     Data16 (dpy, (short *) rects, nbytes);
    266     UnlockDisplay(dpy);
    267     SyncHandle();
    268 }
    269 
    270 
    271 void XShapeCombineMask (
    272     register Display *dpy,
    273     XID dest,
    274     int destKind,
    275     int xOff, int yOff,
    276     Pixmap src,
    277     int op)
    278 {
    279     XExtDisplayInfo *info = find_display (dpy);
    280     register xShapeMaskReq *req;
    281 
    282     ShapeSimpleCheckExtension (dpy, info);
    283 
    284     LockDisplay(dpy);
    285     GetReq(ShapeMask, req);
    286     req->reqType = info->codes->major_opcode;
    287     req->shapeReqType = X_ShapeMask;
    288     req->op = op;
    289     req->destKind = destKind;
    290     req->dest = dest;
    291     req->xOff = xOff;
    292     req->yOff = yOff;
    293     req->src = src;
    294     UnlockDisplay(dpy);
    295     SyncHandle();
    296 }
    297 
    298 void XShapeCombineShape (
    299     register Display *dpy,
    300     XID dest,
    301     int destKind,
    302     int xOff, int yOff,
    303     XID src,
    304     int srcKind,
    305     int op)
    306 {
    307     XExtDisplayInfo *info = find_display (dpy);
    308     register xShapeCombineReq *req;
    309 
    310     ShapeSimpleCheckExtension (dpy, info);
    311 
    312     LockDisplay(dpy);
    313     GetReq(ShapeCombine, req);
    314     req->reqType = info->codes->major_opcode;
    315     req->shapeReqType = X_ShapeCombine;
    316     req->op = op;
    317     req->destKind = destKind;
    318     req->srcKind = srcKind;
    319     req->dest = dest;
    320     req->xOff = xOff;
    321     req->yOff = yOff;
    322     req->src = src;
    323     UnlockDisplay(dpy);
    324     SyncHandle();
    325 }
    326 
    327 void XShapeOffsetShape (
    328     register Display *dpy,
    329     XID dest,
    330     int destKind,
    331     int xOff, int yOff)
    332 {
    333     XExtDisplayInfo *info = find_display (dpy);
    334     register xShapeOffsetReq *req;
    335 
    336     ShapeSimpleCheckExtension (dpy, info);
    337 
    338     LockDisplay(dpy);
    339     GetReq(ShapeOffset, req);
    340     req->reqType = info->codes->major_opcode;
    341     req->shapeReqType = X_ShapeOffset;
    342     req->destKind = destKind;
    343     req->dest = dest;
    344     req->xOff = xOff;
    345     req->yOff = yOff;
    346     UnlockDisplay(dpy);
    347     SyncHandle();
    348 }
    349 
    350 Status XShapeQueryExtents (
    351     register Display *dpy,
    352     Window window,
    353     int *bShaped, int *xbs, int *ybs, unsigned int *wbs, unsigned int *hbs, /* RETURN */
    354     int *cShaped, int *xcs, int *ycs, unsigned int *wcs, unsigned int *hcs /* RETURN */)
    355 {
    356     XExtDisplayInfo *info = find_display (dpy);
    357     xShapeQueryExtentsReply	    rep;
    358     register xShapeQueryExtentsReq *req;
    359 
    360     ShapeCheckExtension (dpy, info, 0);
    361 
    362     LockDisplay (dpy);
    363     GetReq (ShapeQueryExtents, req);
    364     req->reqType = info->codes->major_opcode;
    365     req->shapeReqType = X_ShapeQueryExtents;
    366     req->window = window;
    367     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
    368 	UnlockDisplay (dpy);
    369 	SyncHandle ();
    370 	return 0;
    371     }
    372     *bShaped = rep.boundingShaped;
    373     *cShaped = rep.clipShaped;
    374     *xbs = cvtINT16toInt (rep.xBoundingShape);
    375     *ybs = cvtINT16toInt (rep.yBoundingShape);
    376     *wbs = rep.widthBoundingShape;
    377     *hbs = rep.heightBoundingShape;
    378     *xcs = cvtINT16toInt (rep.xClipShape);
    379     *ycs = cvtINT16toInt (rep.yClipShape);
    380     *wcs = rep.widthClipShape;
    381     *hcs = rep.heightClipShape;
    382     UnlockDisplay (dpy);
    383     SyncHandle ();
    384     return 1;
    385 }
    386 
    387 
    388 void XShapeSelectInput (
    389     register Display *dpy,
    390     Window window,
    391     unsigned long mask)
    392 {
    393     XExtDisplayInfo *info = find_display (dpy);
    394     register xShapeSelectInputReq   *req;
    395 
    396     ShapeSimpleCheckExtension (dpy, info);
    397 
    398     LockDisplay (dpy);
    399     GetReq (ShapeSelectInput, req);
    400     req->reqType = info->codes->major_opcode;
    401     req->shapeReqType = X_ShapeSelectInput;
    402     req->window = window;
    403     if (mask & ShapeNotifyMask)
    404 	req->enable = xTrue;
    405     else
    406 	req->enable = xFalse;
    407     UnlockDisplay (dpy);
    408     SyncHandle ();
    409 }
    410 
    411 unsigned long XShapeInputSelected (register Display *dpy, Window window)
    412 {
    413     XExtDisplayInfo *info = find_display (dpy);
    414     register xShapeInputSelectedReq *req;
    415     xShapeInputSelectedReply	    rep;
    416 
    417     ShapeCheckExtension (dpy, info, False);
    418 
    419     LockDisplay (dpy);
    420     GetReq (ShapeInputSelected, req);
    421     req->reqType = info->codes->major_opcode;
    422     req->shapeReqType = X_ShapeInputSelected;
    423     req->window = window;
    424     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
    425 	UnlockDisplay (dpy);
    426 	SyncHandle ();
    427 	return False;
    428     }
    429     UnlockDisplay (dpy);
    430     SyncHandle ();
    431     return rep.enabled ? ShapeNotifyMask : 0L;
    432 }
    433 
    434 
    435 XRectangle *XShapeGetRectangles (
    436     register Display *dpy,
    437     Window window,
    438     int kind,
    439     int *count, /* RETURN */
    440     int *ordering /* RETURN */)
    441 {
    442     XExtDisplayInfo *info = find_display (dpy);
    443     register xShapeGetRectanglesReq   *req;
    444     xShapeGetRectanglesReply	    rep;
    445     XRectangle			    *rects;
    446     xRectangle			    *xrects;
    447     unsigned int		    i;
    448 
    449     ShapeCheckExtension (dpy, info, (XRectangle *)NULL);
    450 
    451     LockDisplay (dpy);
    452     GetReq (ShapeGetRectangles, req);
    453     req->reqType = info->codes->major_opcode;
    454     req->shapeReqType = X_ShapeGetRectangles;
    455     req->window = window;
    456     req->kind = kind;
    457     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
    458 	UnlockDisplay (dpy);
    459 	SyncHandle ();
    460 	return (XRectangle *)NULL;
    461     }
    462     *count = rep.nrects;
    463     *ordering = rep.ordering;
    464     rects = NULL;
    465     if (rep.nrects) {
    466 	if (rep.nrects < (INT_MAX / sizeof (XRectangle))) {
    467 	    xrects = Xmallocarray (rep.nrects, sizeof (xRectangle));
    468 	    rects = Xmallocarray (rep.nrects, sizeof (XRectangle));
    469 	} else {
    470 	    xrects = NULL;
    471 	    rects = NULL;
    472 	}
    473 	if (!xrects || !rects) {
    474 	    Xfree (xrects);
    475 	    Xfree (rects);
    476 	    _XEatDataWords (dpy, rep.length);
    477 	    rects = NULL;
    478 	    *count = 0;
    479 	} else {
    480 	    _XRead (dpy, (char *) xrects, rep.nrects * sizeof (xRectangle));
    481 	    for (i = 0; i < rep.nrects; i++) {
    482 	    	rects[i].x = (short) cvtINT16toInt (xrects[i].x);
    483 	    	rects[i].y = (short) cvtINT16toInt (xrects[i].y);
    484 	    	rects[i].width = xrects[i].width;
    485 	    	rects[i].height = xrects[i].height;
    486 	    }
    487 	    Xfree (xrects);
    488 	}
    489     }
    490     UnlockDisplay (dpy);
    491     SyncHandle ();
    492     return rects;
    493 }
    494