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;
}