11-18-05 10:54 PM
Recently I posted a message to this group titled "XShape
example(s)?" [http://tinyurl.com/7qndk]. With much assistance, I
was able to generate a simple example program for using the XShape
extension to achieve true transparency in Xlib.
So now I'm experimenting with pseudo-transparency. If you're
interested, see the attached program below. For the most part, it
works, however, the pseudo-transparent background is skewed a bit.
I believe that is simply a matter of correcting where I crop from
the root image (e.g. make up for window manager borders).
What I'm really struggling with is XGetGeometry(). Regardless of
*my* window's position, XGetGeometry() always returns (0, 0). Using
XGetGeometry() my window's parent gives me non-zero---but still
constant---values. Using the grandparent of my window actually
yields the "true" window position (I say "true" in quotes because
I'm not sure if it's the exact position or not, but it's pretty
close).
The point is, I'm not sure if this is the most generic way to get
the window position. I was playing with this a bit on a Windows box
using Exceed, and I was able to get window position updates using my
window's parent.
Anyway, for those who are interested, here's my pseudo-transparency
example (as a work-in-progress).
Thanks!
Matt
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <unistd.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 }
};
Pixmap x_get_root_pixmap_by_property(Display *dpy);
Pixmap x_get_cropped_pixmap(Display *dpy, Pixmap src, int x, int y,
unsigned width, unsigned height);
int main(int argc, char **argv)
{
Display *dpy = NULL;
Window w;
Pixmap pmap = None;
GC win_gc;
XGCValues xgcv;
int run = 1; /* loop control variable */
/* open the display */
if (!(dpy = XOpenDisplay(0))) {
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);
XSetWindowBackgroundPixmap(dpy, w, x_get_root_pixmap_by_property(dpy));
/* 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);
/* register events: ExposureMask for re-drawing, ButtonPressMask
* to capture mouse button press events */
XSelectInput(dpy, w, ButtonPressMask | ExposureMask);
/* map the window - tell the world that it is to be seen */
XMapWindow(dpy, w);
XSync(dpy, False);
while (run) {
XEvent xe;
XNextEvent(dpy, &xe);
Window root, parent, *children;
int x, y;
unsigned int width, height, border_width, depth, nchildren;
static int expose_count = 0;
switch (xe.type) {
case GraphicsExpose:
printf("GraphicsExpose\n");
break;
case Expose:
printf("Expose %i\n", expose_count++);
XQueryTree(dpy, w, &root, &parent, &children, &nchildren);
XQueryTree(dpy, parent, &root, &parent, &children,
&nchildren);
XGetGeometry(dpy, parent, &root, &x, &y, &width, &height,
&border_width, &depth);
printf("x = %i, y = %i\n", x, y);
pmap = x_get_cropped_pixmap(dpy,
x_get_root_pixmap_by_property(dpy), x, y, width,
height);
/* whenever we get an expose, draw the rectangles */
XClearWindow(dpy, w);
XSetWindowBackgroundPixmap(dpy, w, pmap);
XSetForeground(dpy, win_gc, WhitePixel(dpy,
DefaultScreen(dpy)));
XDrawRectangles(dpy, w, win_gc, rectangles, 4);
XFillRectangles(dpy, w, win_gc, rectangles, 4);
break;
case ButtonPress: /* quit if a button is pressed */
printf("ButtonPress\n");
run = 0;
break;
case NoExpose:
printf("NoExpose\n");
break;
default:
printf("Caught event %i\n", xe.type);
}
}
XDestroyWindow(dpy, w);
XCloseDisplay(dpy);
return EXIT_SUCCESS;
}
Pixmap x_get_root_pixmap_by_property(Display *dpy)
{
Pixmap root_pixmap = None;
static Atom id = None;
const char* pixmap_id_names[] = {
"_XROOTPMAP_ID", "ESETROOT_PMAP_ID", NULL
};
int i = 0;
for (i=0; (pixmap_id_names[i] && (None == root_pixmap)); i++) {
if (None == id) {
id = XInternAtom(dpy, pixmap_id_names[i], True);
}
if (None != id) {
Atom actual_type = None;
int actual_format = 0;
unsigned long nitems = 0;
unsigned long bytes_after = 0;
unsigned char *properties = NULL;
int rc = 0;
rc = XGetWindowProperty(dpy, DefaultRootWindow(dpy), id, 0, 1,
False, XA_PIXMAP, &actual_type, &actual_format, &nitems,
&bytes_after, &properties);
if (Success == rc && properties) {
root_pixmap = *((Pixmap*)properties);
}
}
}
return root_pixmap;
}
Pixmap x_get_cropped_pixmap(Display *dpy, Pixmap src, int x, int y,
unsigned width, unsigned height)
{
Pixmap dest = None;
Status rc;
Window root_return = None;
int x_return = 0;
int y_return = 0;
unsigned int width_return = 0;
unsigned int height_return = 0;
unsigned int border_width_return = 0;
unsigned int depth_return = 0;
rc = XGetGeometry(dpy, src, &root_return, &x_return, &y_return,
&width_return, &height_return, &border_width_return,
&depth_return);
dest = XCreatePixmap(dpy, src, width, height, depth_return);
if (None != dest) {
rc = XCopyArea(dpy, src, dest, DefaultGC(dpy, 0), x, y, width,
height, 0, 0);
}
return dest;
}
[ Post a follow-up to this message ]
|