SHAPE supports nonrectangular windows. In the core protocol, a window can be thought of as being defined by three rectangles: a bounding rectangle (a window's outside size, including its border), a clip rectangle (a window's inside size, not including its border), and an input rectangle (defined as the area of the screen within which the pointer hotspot is considered to be in the window, or would be so considered were it not for other windows occluding it; in the core protocol, this is identical to the bounding rectangle). (But see below about input regions and liblx's support.) With SHAPE, each of these three may be nonrectangular; they are, thus, called `region's rather than `rectangle's. Also, depending on the version of SHAPE, the input region may or may not be required to be identical to the bounding region. This document uses the adjective `default', as in speaking of a window's default bounding region, to refer to the rectangular regions used by the core protocol; an `effective' region is the region actually used by the server to clip operations or determine whether the pointer is within the window. A `client' region is a region specified by a client. The effective regions are computed from the corresponding default and client regions and in some cases other regions (specifically, the effective bounding region is the client bounding region intersected with the default bounding region; the effective clip region is the client clip region intersected with both the default clip region and the client bounding region; and the effective input region is the client input region intersected with both the default input region and the client bounding region. When there is no client region of a particular type, effective regions are computed as if that client region were infinite in all four directions - or, equivalently, as if it were identical to the default bounding region, since all effective regions are clipped by the default bounding region. Effective region computation is dynamic; for example, if a client specifies a bounding region which extends beyond the default bounding region, the effective bounding region is limited by the default bounding region, but, if the default bounding region is later enlarged (eg, by a ConfigureWindow request), the effective bounding region will be enlarged to the intersection of the previously-specified client bounding region with the new default bounding region. The border of a window is defined as that part of the effective bounding region which is not also part of the effective clip region. Thus, for example, a window with a border-width of zero may still have a visible border, since, even though in that case the default clip region is identical to the default bounding region, the client clip region may be smaller than the effective bounding region. A window's origin (as used by graphics operations, tiling, and subwindow placement) is not affected by the client region settings. If the window size as specified in the core protocol is W by H, and its border width is BW, then, relative to the window's origin, the default bounding and input regions are identical rectangles x = -BW y = -BW w = W + (2 * BW) h = H + (2 * BW) and the default clip region is a rectangle x = 0 y = 0 w = W h = H Client specification of shaped regions is modeled on the way clipping regions are specified for GCs in the core protocol (see gc.txt): a region can be specified as a list of rectangles, as a bitmap (a depth-1 pixmap), or as one of the existing regions of some window. In each case, the specified region is combined with the existing region in one of five ways; see below for details. (When one of a window's regions is necessary, as either a source or a destination, if none has been set then the corresponding default region is used.) InputOnly windows have bounding and input regions, but they do not have clip regions; attempting to set or use the clip region of an InputOnly window is a Match error. Older versions of SHAPE do not have input regions. The liblx API to SHAPE has no support for input regions, pending deciding how I want to support both versions. It also has no support for SHAPE events, pending my designing APIs to support extension events. Here are the routines for the liblx SHAPE API. As for core routines (see core.txt), routines that return data through pointer arguments accept nil pointers for these arguments; when this is done, the information that would normally be written through that argument is not saved anywhere. (When it would normally be allocated data such as a struct or a data buffer, the memory either is freed within liblx or isn't allocated at all.) Also, when a routine which returns an LX_OP * also has pointer arguments through which values are potentially returned (which is most of the LX_OP-returning routines), writes through the arguments always happen at some point or points in time, indeterminate from the application's point of view, after entry to the API routine and before the returned LX_OP completes. (See pending-operations.txt for more.) The first arg to all these is the relevant LX_CONN; it is not mentioned in the text descriptions below. Types: LX_SHAPE_KIND LX_SHAPE_Bounding or LX_SHAPE_Clip, specifying whether the associated region is a bounding region or a clip region. LX_SHAPE_Input is not currently defined; it will refer to input regions once I implement them. LX_SHAPE_OP Specifies how to combine two regions. Given a source region and a destination region, the operation specifies how the resulting region (which replaces the destination region) is computed (after shifting the source): LX_SHAPE_Set The resulting region is the source region. LX_SHAPE_Union The resulting region is the union of the source and destination regions. LX_SHAPE_Intersect The resulting region is the intersection of the source and destination regions. LX_SHAPE_Subtract The resulting region is the destination region intersected with the complement of the source region. LX_SHAPE_Invert The resulting region is the source region intersected with the complement of the destination region. To put it another way, when considering whether a point belongs to the destination region, where S is true iff it belongs to the source region and D is true iff it belongs to the destination region, then R, the resulting boolean indicating whether the point belongs to the resulting region, is LX_SHAPE_Set R = S LX_SHAPE_Union R = S | D LX_SHAPE_Intersect R = S & D LX_SHAPE_Subtract R = D & !S LX_SHAPE_Invert R = S & !D There are eleven more conceivable boolean operations (see the description of Function in gc.txt); they are not supported for SHAPE. The omitted operations are (to use GC function names) Clear, NoOp, Xor, and the eight which produce a 1 when both input bits are 0. I don't know why they were omitted. I suspect the eight were omitted to simplify implementations by allowing the conceptual infinite surround to be always 0. Clear is equivalent to ShapeMask with None for the pixmap, and NoOp is equivalent to not performing the relevant operation at all. But I really do not understand omitting Xor. LX_SHAPE_EXTENTS A struct type used by lx_shape_QueryExtents_extents to collect the values returned by ShapeQueryExtents. It consists of a bitmask, shaped, which has bits LX_SHAPED_Bounding and LX_SHAPED_Clip, indicating which of the target window's regions have client regions set, and two LX_RECTANGLEs, bounding and clip, which contain the returned bounds for, respectively, the bounding and clip regions. The protocol does not support returning information about the clip region (I don't know why not; perhaps they don't want to version their calls). lx_shape_query -------------- LX_OP *lx_shape_query(LX_CONN *c, int *supp) Query whether SHAPE is supported. supp is written with 0 if the extension is absent or is not compatible with liblx, 1 if it is usable. Using any of the other SHAPE support routines on an LX_CONN produces undefined behaviour unless this one has indicated support for that LX_CONN first. It is also an error to call this on an LX_CONN and then, before that call has completed, call it again on the same LX_CONN. lx_shape_Rectangles ------------------- void lx_shape_Rectangles(LX_CONN *c, LX_XID dstwin, LX_SHAPE_KIND dstkind, LX_SHAPE_OP op, int xoff, int yoff, LX_RECTORDER ord, int nrects, const LX_RECTANGLE *rects) Issues a ShapeRectangles request, combining a region specified as a list of rectangles, offset by specified amounts in X and Y, with a destination region. dstwin and dstkind specify the destination region. op specifies which operation is used void lx_shape_Mask(LX_CONN *c, LX_XID dstwin, LX_SHAPE_KIND dstkind, LX_SHAPE_OP op, int xoff, int yoff, LX_XID src) void lx_shape_Combine(LX_CONN *c, LX_XID dstwin, LX_SHAPE_KIND dstkind, LX_SHAPE_OP op, int xoff, int yoff, LX_XID src, LX_SHAPE_KIND srckind) void lx_shape_Offset(LX_CONN *c, LX_XID dstwin, LX_SHAPE_KIND dstkind, int xoff, int yoff); // shapedp uses the same bits as LX_SHAPE_EXTENTS.shaped LX_OP *lx_shape_QueryExtents(LX_CONN *c, LX_XID win, unsigned int *shapedp, int *bbxp, int *bbyp, int *bbwp, int *bbhp, int *clixp, int *cliyp, int *clipwp, int *cliphp) LX_OP *lx_shape_QueryExtents_extents(LX_CONN *c, LX_XID win, LX_SHAPE_EXTENTS *extp) void lx_shape_SelectInput(LX_CONN *c, LX_XID win, int enb) LX_OP *lx_shape_InputSelected(LX_CONN *c, LX_XID win, int *enbp) // rect list is allocated by library, freeable with free LX_OP *lx_shape_GetRectangles(LX_CONN *c, LX_XID win, LX_SHAPE_KIND kind, LX_RECTORDER *ord, int *nrectp, LX_RECTANGLE **rectsp)