Unix Programming - Xlib pseudo transparency example (needs polish)

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > November 2005 > Xlib pseudo transparency example (needs polish)





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Xlib pseudo transparency example (needs polish)
Matt Garman

2005-11-18, 5: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;
}


Måns Rullgård

2005-11-19, 7:47 am

Matt Garman <fake@not-real.bogus> writes:

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


You can use XTranslateCoordinates with the root window and your window
as two of the arguments.

Followups set to c.w.x, as that is more appropriate than c.u.p.

--
Måns Rullgård
mru@inprovide.com
E. Rosten

2005-11-19, 7:47 am

On Fri, 18 Nov 2005 23:33:23 +0000, Matt Garman wrote:


> 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.


This is correct: the window manager reparents any windows on the root
window and sticks them inside its own window, so that it can add
decorations, etc. You probably want XGetGeometry relative to the root
window. There was a previous discussion about that here, and I believe
that the conclusion was that it is pretty much impossible to do this
without a round trip to the server.

You can in general snip out one branch of the window tree and move it
elsewhere with XReparentWindow.


-Ed

--
(You can't go wrong with psycho-rats.) (er258)(@)(eng.cam)(.ac.uk)

/d{def}def/f{/Times findfont s scalefont setfont}d/s{10}d/r{roll}d f 5/m
{moveto}d -1 r 230 350 m 0 1 179{1 index show 88 rotate 4 mul 0 rmoveto}
for /s 15 d f pop 240 420 m 0 1 3 { 4 2 1 r sub -1 r show } for showpage

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com