Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xlib: XGetWindowAttributes always returns 1x1?

Tags:

c++

c

xorg

xlib

I'd like to have width and height of the currently focussed window. The selection of the window works like a charm whereas the height and width are always returning 1.

#include <X11/Xlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    Display *display;
    Window focus;
    XWindowAttributes attr;
    int revert;

    display = XOpenDisplay(NULL);
    XGetInputFocus(display, &focus, &revert);
    XGetWindowAttributes(display, focus, &attr);
    printf("[0x%x] %d x %d\n", (unsigned)focus, attr.width, attr.height);

    return 0;
}

Is this not the "real" window but the currently active component (like a textbox or a button?) And why would it have the size of 1x1 anyways then? If this is the case, how do i get the main window of the application containig this control? Means... kinda the top-level window, the top-most window except the root window.

PS: Don't know whether it's really important; I use Ubuntu 10.04 32 and 64 bit.

like image 269
Atmocreations Avatar asked Oct 11 '10 20:10

Atmocreations


1 Answers

You're right - you're seeing a child window. GTK applications, in particular, create a child window under the "real" window, which is always 1x1, and that always gets the focus when the application has the focus. If you're just running your program using the GNOME terminal, you'll always be seeing a GTK application with the focus (the terminal).

If you run your program in such a way that a non-GTK program happens to have the focus, then this doesn't happen, but you could still end up finding a child window with the focus instead of the top-level window. (One way of doing this is to run sleep before your program like this: sleep 4; ./my_program - this gives you a chance to change the focus.)

To find the top-level window, I think XQueryTree will help - it returns the parent window.

This worked for me:

#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>

/*
Returns the parent window of "window" (i.e. the ancestor of window
that is a direct child of the root, or window itself if it is a direct child).
If window is the root window, returns window.
*/
Window get_toplevel_parent(Display * display, Window window)
{
     Window parent;
     Window root;
     Window * children;
     unsigned int num_children;

     while (1) {
         if (0 == XQueryTree(display, window, &root,
                   &parent, &children, &num_children)) {
             fprintf(stderr, "XQueryTree error\n");
             abort(); //change to whatever error handling you prefer
         }
         if (children) { //must test for null
             XFree(children);
         }
         if (window == root || parent == root) {
             return window;
         }
         else {
             window = parent;
         }
     }
}

int main(int argc, char *argv[])
{
    Display *display;
    Window focus, toplevel_parent_of_focus;
    XWindowAttributes attr;
    int revert;

    display = XOpenDisplay(NULL);
    XGetInputFocus(display, &focus, &revert);
    toplevel_parent_of_focus = get_toplevel_parent(display, focus);
    XGetWindowAttributes(display, toplevel_parent_of_focus, &attr);
    printf("[0x%x] %d x %d\n", (unsigned)toplevel_parent_of_focus, 
       attr.width, attr.height);

    return 0;
}
like image 84
Doug Avatar answered Sep 18 '22 12:09

Doug