tags:

views:

383

answers:

2

I am attempting to get the X Window at a certain location on screen. When I asked people for a function to do this, they said you would just call XQueryTree recursively.

This is the code snippet which I think is somehow wrong. When I debug it, it seems to work perfectly. The only problem is that the output it gives seems a little strange. When I do XQueryTree on the root window, I get hundreds of children, when I only have five or so open. Also, it seems to think that there is a top-level window somewhere where there simply isn't one, and returns it as a result. No matter how I move my actual windows around, XQueryTree seems to indicate that there is another window on top of my windows (not covering the entire screen.) When I look at where it says the window is, it is at some arbitrary point on my desktop.

If this is of any help: The display is from XOpenDisplay(NULL), and the root window I originally pass it is XDefaultRootWindow(display). I am running gnome under debian with metacity.

point getwindowatloc(Display * display, Window root, jint x, jint y) {
     Window returnedroot;
     Window returnedparent;
     Window * children;
     unsigned int numchildren;
     XQueryTree(display,root,&returnedroot,&returnedparent,&children, &numchildren);
     XWindowAttributes w;
     int i;
     for(i=numchildren-1; i>=0; i--) {
      XGetWindowAttributes(display,children[i],&w); 
      if(x>=w.x && x<=w.x+w.width && y>=w.y && y <= w.y+w.height) {
       point result={w.x,w.y};
       XFree(children);
       return result;
      } else {
       point result=getwindowatloc(display,children[i],x-w.x,y-w.y);
       if(result.x!=INT_MAX) {
        result.x+=w.x;
        result.y+=w.y;
        XFree(children);
        return result;
       }
      }
     }
     if(children) {
      XFree(children);
     }
     return notfound;
    }

Thanks!

EDIT: For anyone who is searching for similar information: I ended up looking into the source of xwininfo. The key function is Find_Client in dsimple.c, which somehow ignores window managers to get the window you are actually looking for. If you want to look into subwindows, this is some code I added to Select_Window in dsimple.c which will recursively look inside subwindows, using XTranslateCoordinates.

Window child;
do {
  XTranslateCoordinates(dpy,target_temp,target_win,x,y,&x,&y,&child);
  target_temp=target_win;
  target_win=child;
} while(target_win);
return target_temp;
+2  A: 

Your code looks right (I haven't tested it), and the results you describe don't seem strange at all. Metacity (and other X window managers) will create lots of windows around and near the application-owned windows to show the window title, borders and other decorations.

Try running your test with some simpler window manager like TVM (or even none at all). TVM should create a lot less windows than current window managers. This should make things easier to understand.

Usually, however, it's a bad idea to fight against the window manager. Can't you solve your problem in a higher level way withour having to use xlib directly?

Ricardo Massaro
The idea was that I wanted to write something that would work on as man platforms as possible. I figured if I wrote it for xlib, it would be be portable to many systems, rather than just working for the window manager I use. I will try using it with a different window manager next.
Jeremybub
+1  A: 

I think what you want to do is query the root window's _NET_CLIENT_LIST property. This will produce a list of Window IDs for all client windows, excluding all of the "virtual" windows created by the window manager. Most window managers apparently support _NET_CLIENT_LIST, but you can also query whether or not any given feature is supported.

rob
Thank you, but I found something else that works. I am using a fuction from xwininfo to do the work. It might do exactly what you are suggesting, I'm not sure. Thanks for the help.
Jeremybub
Cool, glad to hear you found a workaround. :)
rob