XShape example?

Carsten Haitzler (The Rasterman) raster at rasterman.com
Fri Oct 28 21:38:59 PDT 2005


On Fri, 28 Oct 2005 23:20:17 -0500 Matt Garman <garman at raw-sewage.net> babbled:

> 
> I was wondering if anyone out there has some simple code that
> demonstrates the usage of the "X Nonrectangular Window Shape
> Extension Library" (XShape)?
> 
> I've read (and re-read) Keith Packard's document:
> 
>     http://www.x.org/X11R6.8.1/docs/Xext/shape.pdf
>     http://www.xfree86.org/current/shapelib.pdf
> 
> I've also tried to use the xeyes, xlogo and oclock sources as an
> example, but I'm just not getting it (plus those example all use the
> "Xt" API, whereas I'd prefer not to use that, and I'm not sure what
> all the Xt stuff is doing "behind the scenes").
> 
> Right now, I'd like to create windows that have
> "pseudo-transparency", such as xeyes does (e.g. the area around the
> eyes looks as though it's transparent).  [BTW, I know it's not true
> transparency, but as long as it *looks* transparent, that's good
> enough for me.]

it is true transparency. no pixels exist in the "shaped out" areas - you see
right through it - events go through the holes too. its the oldes form of
transparency x has - but effectively only provides 1 bit of accuracy :) (i wont
go into how its implemented with rectangle lists) :)

> An ideal example program would be one that creates a window with a
> "transparent" background, and draws a white block somewhere in the
> window.
> 
> Attached below is a program which attempts to do just that---create
> a "transparent" window, and upon it draw four white boxes, one in
> each corner of the window.
> 
> However, all I get is a blank "transparent" window---no boxes are
> drawn, and the background does not update if the window is moved.
> Also interesting is that the program does not recognize mouse button
> presses.
> 
> If I remove the few lines of code that try to establish
> transparency, and replace with a XSetWindowBackground(), the program
> works as expected (draws the white boxes on a solid, opaque
> background).  So I believe I've got things mostly right, but my use
> of XShapeCombineMask() isn't correct.
> 
> Any thoughts?
> 
> Thank you,
> Matt
> 
> -- 
> Matt Garman
> email at: http://raw-sewage.net/index.php?file=email
> 
> 
> 
> /* Save as: 'xshape_example.c'
>  * Compiling: 
>  * gcc -Wall -g xshape_example.c -o xshape_example -lX11 -lXext
>  */
> 
> /* This program *attempts* to create a "transparent" window (using
>  * the XShape extension) and draw four white (opaque) squares in
>  * each corner of the window
>  */
> 
> #include <string.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <X11/Xlib.h>
> #include <unistd.h>
> #include <X11/Xutil.h>
> #include <X11/extensions/shape.h>
> 
> /* size of the window */
> #define W_WIDTH 640
> #define W_HEIGHT 480
> 
> /* size of the four rectangles that will be drawn in the window */
> #define R_WIDTH 80
> #define R_HEIGHT 60
> 
> Display *dpy;
> Window w;
> 
> /* convenience variables */
> int BLACK_PIXEL;
> int WHITE_PIXEL;
> 
> /* the four rectangles that will be drawn: one in each corner of the
>  * window */
> XRectangle rectangles[4] =
> {
>     { 0, 0, R_WIDTH, R_HEIGHT },
>     { 0, W_HEIGHT-R_HEIGHT, R_WIDTH, R_HEIGHT },
>     { W_WIDTH-R_WIDTH, W_HEIGHT-R_HEIGHT, R_WIDTH, R_HEIGHT },
>     { W_WIDTH-R_WIDTH, 0, R_WIDTH, R_HEIGHT }
> };
>         
> int main(int argc, char **argv)
> {
>     XGCValues shape_xgcv;
>     Pixmap pmap;
>     GC shape_gc;
>     GC gc;
>     XGCValues gcv;
>     int run = 1; /* loop control variable */
> 
>     /* open the display */
>     if(!(dpy = XOpenDisplay(getenv("DISPLAY")))) {
>         fprintf(stderr, "can't open display\n");
>         return EXIT_FAILURE;
>     }
> 
>     /* convenience */
>     BLACK_PIXEL = BlackPixel(dpy, DefaultScreen(dpy));
>     WHITE_PIXEL = WhitePixel(dpy, DefaultScreen(dpy));
> 
>     w = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0,
>             W_WIDTH, W_HEIGHT, 0, CopyFromParent,
>             InputOutput, CopyFromParent, 0, NULL);
>     
>     /* Try to create a transparent background.
>      *
>      * The idea/technique attempts to mimic lines 342--360 of
>      * "Eyes.c", from the "xeyes" source.  (The xeyes source is part
>      * of the X11 source package.)
>      *
>      * Every other example I've seen uses a pixmap, but I'd like to
>      * not have a pixmap as a requirement.
>      */
>     pmap = XCreatePixmap(dpy, w, W_WIDTH, W_HEIGHT, 1);
>     shape_gc = XCreateGC(dpy, pmap, 0, &shape_xgcv);
>     XSetForeground(dpy, shape_gc, 0);
>     XFillRectangle(dpy, pmap, shape_gc, 0, 0, W_WIDTH, W_HEIGHT);
> 
>     XShapeCombineMask (dpy, w, ShapeBounding,
>             0, 0, pmap, ShapeSet);
> 
>     /* If I remove everything above (until the comment), and replace
>      * with the following, this application works as expected (e.g.,
>      * draws a black window with white rectanles at each corner */
>     /* XSetWindowBackground(dpy, w, BLACK_PIXEL); */
> 
>     /* create a graphics context for drawing */
>     gcv.foreground = WHITE_PIXEL;
>     gcv.line_width = 1;
>     gcv.line_style = LineSolid;
>     gc = XCreateGC(dpy, w,
>             GCForeground | GCLineWidth | GCLineStyle, &gcv);
> 
>     /* register events: ExposureMask for re-drawing, ButtonPressMask
>      * to capture mouse button press events */
>     XSelectInput(dpy, w, ExposureMask | ButtonPressMask);
> 
>     XMapWindow(dpy, w);
>     XSync(dpy, False);
> 
>     while(run) {
>         XEvent xe;
>         XNextEvent(dpy, &xe);
>         switch (xe.type) {
>             case Expose:
>                 /* whenever we get an expose, draw the rectangles */
>                 XSetForeground(dpy, gc, WHITE_PIXEL);
>                 XDrawRectangles(dpy, w, gc, rectangles, 4);
>                 XFillRectangles(dpy, w, gc, rectangles, 4);
>                 XSync(dpy, False);
>                 break;
>             case ButtonPress: /* quit if a button is pressed */
>                 /* note that when using XShapeCombineMask(), i.e.
>                  * trying to get a "transparent" background,
>                  * no ButtonPress events are ever recognized
>                  */
>                 printf("ButtonPress\n");
>                 run = 0;
>                 break;
>             default:
>                 printf("Caught event %i\n", xe.type);
>         }
>     }
> 
>     XDestroyWindow(dpy, w);
>     XCloseDisplay(dpy);
> 
>     return 0;
> }

see where you draw the rectangles - you want to ALSO draw them to the shape
pixmap and combine that shape pixmap (again) as when you SET the shape its
SEPARATe from the pixel contents of the window. you set up a blank shape
(nothing in it). you want to fill it with 1 rects of value "1" (0 == blank in
the mask, 1 = visible). you can also set the shape rectangles directly if that
tickles your fancy  :)

> 
> _______________________________________________
> xorg mailing list
> xorg at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xorg
> 


-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
The Rasterman (Carsten Haitzler)    raster at rasterman.com
裸好多
Tokyo, Japan (東京 日本)



More information about the xorg mailing list