XShape example?

Matt Garman garman at raw-sewage.net
Sat Oct 29 01:42:53 PDT 2005


On Sat, Oct 29, 2005 at 01:38:59PM +0900, Carsten Haitzler wrote:
> On Fri, 28 Oct 2005 23:20:17 -0500 Matt Garman
> <garman at raw-sewage.net> babbled:
> > 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) :)

Ahh, now that I have a working example, I see that it is in fact
true transparency.

When you say that this is the "oldest form of transparency x has",
does that imply there are *better* ways of doing transparency?

As a general disclaimer, I'm just getting into Xlib programming, so
it's safe to assume total ignorance on my part!

> 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  :)

You are a godsend, thank you so much!  I've been struggling with
this for so long now (does this stuff take a while for everybody?
Man, I hope so, and please don't say otherwise if only for my ego!).

Anyway, I have a working version of the program now.  I'm not sure
if I'm doing it 100% correctly, but it does work as advertised!
I'll take that as a victory, given the amount of time I've spent
trying to get it to work (and not knowing where to get additional
information).

I've attached the little sample program below; hopefully it will be
useful for posterity (if nothing else!).

Thanks again!

Matt

-- 
Matt Garman
email at: http://raw-sewage.net/index.php?file=email




/* This program creates 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

/* 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)
{
    Display *dpy;
    Window w;
    Pixmap pmap;
    GC shape_gc;
    GC win_gc;
    XGCValues xgcv;
    int run = 1; /* loop control variable */

    /* open the display */
    if(!(dpy = XOpenDisplay(getenv("DISPLAY")))) {
        fprintf(stderr, "can't open display\n");
        return EXIT_FAILURE;
    }

    /* create the window */
    w = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, W_WIDTH,
            W_HEIGHT, 0, CopyFromParent, InputOutput,
            CopyFromParent, 0, NULL);

    /* create a graphics context for drawing on the window */
    xgcv.foreground = WhitePixel(dpy, DefaultScreen(dpy));
    xgcv.line_width = 1;
    xgcv.line_style = LineSolid;
    win_gc = XCreateGC(dpy, w,
            GCForeground | GCLineWidth | GCLineStyle, &xgcv);

    /* create the pixmap that we'll use for shaping the window */
    pmap = XCreatePixmap(dpy, w, W_WIDTH, W_HEIGHT, 1);

    /* create a graphics context for drawing on the pixmap */
    shape_gc = XCreateGC(dpy, pmap, 0, &xgcv);

    /* register events: ExposureMask for re-drawing, ButtonPressMask
     * to capture mouse button press events */
    XSelectInput(dpy, w, ButtonPressMask | StructureNotifyMask);

    XMapWindow(dpy, w);
    XSync(dpy, False);

    while(run) {
        XEvent xe;
        XNextEvent(dpy, &xe);
        switch (xe.type) {
            case ConfigureNotify:
                printf("ConfigureNotify\n");
                /* whenever we get an expose, draw the rectangles */
                XSetForeground(dpy, shape_gc, 0);
                XFillRectangle(dpy, pmap, shape_gc, 0, 0, W_WIDTH,
                        W_HEIGHT);

                XSetForeground(dpy, shape_gc, 1);
                XDrawRectangles(dpy, pmap, shape_gc, rectangles, 4);
                XFillRectangles(dpy, pmap, shape_gc, rectangles, 4);

                XSetForeground(dpy, win_gc, WhitePixel(dpy,
                            DefaultScreen(dpy)));
                XDrawRectangles(dpy, w, win_gc, rectangles, 4);
                XFillRectangles(dpy, w, win_gc, rectangles, 4);

                XShapeCombineMask (dpy, w, ShapeBounding,
                        0, 0, pmap, ShapeSet);

                XSync(dpy, False);
                break;
            case ButtonPress: /* quit if a button is pressed */
                printf("ButtonPress\n");
                run = 0;
                break;
            default:
                printf("Caught event %i\n", xe.type);
        }
    }

    XFreePixmap(dpy, pmap);
    XDestroyWindow(dpy, w);
    XCloseDisplay(dpy);

    return 0;
}





More information about the xorg mailing list