Xlib: XGetWindowAttributes всегда возвращает 1x1? - PullRequest
3 голосов
/ 12 октября 2010

Я хотел бы иметь ширину и высоту текущего фокусированного окна.Выбор окна работает как шарм, тогда как высота и ширина всегда возвращают 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;
}

Это не «реальное» окно, а активный в данный момент компонент (напримертекстовое поле или кнопка?) И почему тогда он будет иметь размер 1x1?Если это так, как мне получить главное окно приложения, содержащее этот элемент управления?Означает ... своего рода окно верхнего уровня, самое верхнее окно, кроме корневого.

PS: Не знаю, действительно ли это важно;Я использую Ubuntu 10.04 32 и 64 бит.

1 Ответ

9 голосов
/ 14 октября 2010

Вы правы - вы видите дочернее окно. В частности, GTK-приложения создают дочернее окно под «реальным» окном, которое всегда имеет размер 1x1, и оно всегда получает фокус, когда приложение имеет фокус. Если вы просто запускаете свою программу с помощью терминала GNOME, вы всегда будете видеть приложение GTK с фокусом (терминал).

Если вы запустите свою программу таким образом, что у программы, не являющейся GTK, есть фокус, то этого не произойдет, но вы все равно можете найти дочернее окно с фокусом вместо верхнего уровня окно. (Один из способов сделать это - запустить sleep перед вашей программой следующим образом: sleep 4; ./my_program - это дает вам возможность изменить фокус.)

Чтобы найти окно верхнего уровня, я думаю, XQueryTree поможет - оно возвращает родительское окно.

Это сработало для меня:

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