XPutImage для DefaultRootWindow() ничего не дает

Я пытаюсь написать заставку, совместимую с пакетом xscreensaver. Это требует, чтобы программа рисовала что-то в корневом окне. Моя программа работает нормально, когда я сам создаю окно без полномочий root, например:

Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0, width, height, 1, 0, 0);

рисование его на

Окно окна = DefaultRootWindow (отображение);

вместо этого ничего не дает. Я пытался запустить его из xscreensaver-demo, из xterm, из среды без оконного менеджера, но все они дают черный цвет. В терминале, откуда я его запускаю, ошибки X11 не отображаются. Также мой обработчик ошибок не срабатывает. Я думаю, что моя самая большая проблема сейчас в том, что я не могу найти (даже с помощью Google), как отлаживать что-то подобное.

Любая помощь приветствуется!

Вот код:

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

void draw(char *rgb_out, int w, int h)
{
        for(int i=0; i<w*h*4; i++)
                *rgb_out++ = rand();
}

XImage *create_ximage(Display *display, Visual *visual, int width, int height)
{
        char *image32 = (char *)malloc(width * height * 4);
        draw(image32, width, height);
        return XCreateImage(display, visual, 24, ZPixmap, 0, image32, width, height, 32, 0);
}

int x11_err_handler(Display *pd, XErrorEvent *pxev)
{
        char msg[4096] = { 0 };
        XGetErrorText(pd, pxev -> error_code, msg, sizeof(msg));
        printf("%s\n", msg);
        return 0;
}

int main(int argc, char **argv)
{
        Display *display = XOpenDisplay(getenv("DISPLAY"));

        Window window = DefaultRootWindow(display);

        XWindowAttributes wa;
        XGetWindowAttributes(display, window, &wa);
        int width = wa.width, height = wa.height;
        printf("res: %dx%d\n", width, height);

        GC gc = XCreateGC(display, window, 0, NULL);
        Visual *visual = DefaultVisual(display, 0);

        XSetErrorHandler(x11_err_handler);

        for(;;)
        {
                XImage *ximage = create_ximage(display, visual, width, height);
                XPutImage(display, window, gc, ximage, 0, 0, 0, 0, width, height);
                XDestroyImage(ximage);

                XFlush(display);

                usleep(50000);
        }

        return 0;
}

Его можно скомпилировать с помощью:

g++ -O3 -lX11 -lXpm so.cpp

person Folkert van Heusden    schedule 10.03.2014    source источник
comment
Вы уверены, что ваше корневое окно видно (не закрыто другим окном?) Попробуйте «xwininfo -tree» и нажмите на рабочий стол. Кроме того, почему вы хотите рисовать на корне? Просто создайте размер окна экрана с переопределением флага перенаправления   -  person Andrey Sidorov    schedule 11.03.2014


Ответы (2)


Ваш код отлично работает для меня, протестирован с Xephyr. Я предполагаю (как я уже прокомментировал), что в вашем корневом окне настройки скрыто DE, например, в Ubuntu может быть «наутилус», работающий в полноэкранном режиме, чтобы обеспечить функциональность выбора рабочего стола / значков / DnD / резиновой ленты.

person Andrey Sidorov    schedule 11.03.2014
comment
Пакет xscreensaver требует записи в корень. Я также протестировал его без каких-либо других окон, закрывающих его: без оконного менеджера и только с xterm. Также запуск из xscreenaver-demo не работает. - person Folkert van Heusden; 11.03.2014

Xscreensaver не требует, чтобы вы рисовали в корневом окне, на самом деле это не сработает. Xscreensaver создает «виртуальный корень», и программы, которые «осведомлены о виртуальном корне», будут рассматривать это виртуальное корневое окно как корневое окно (это не корневое окно). Лучше всего проверить переменные среды, которые устанавливает Xscreensaver (XSCREENSAVER_WINDOW), чтобы найти идентификатор окна виртуального корня и нарисовать его.

person prushik    schedule 15.10.2014