LINUX.ORG.RU

Проблемы с XRenderComposite

 , , ,


1

2

Сделал проект демонстрирующий косяк(?): http://pastebin.com/jtCcRz9B.

Суть в том, что если получить через KWindowSystem::windows() список окон и для каждого сделать скрин через XRender, то если открыто несколько окон одного приложения вместо последнего в скриншоте будет фигня: http://postimg.org/image/3zmrvxtqz/. Если я меняю порядок получения скриншотов на обратный (рассортирую WId от большего к меньшему), то иногда всё нормально: http://postimg.org/image/4c3nbrzyr/, а иногда всё равно косяки при чём на одном и том же окне - окне с большим WId.

Это не зависит от числа открытых окон, если одно - ок, если 2 - косяк со вторым, если 3 - с 3им, и т.д. При чём это только для окон одного приложения, если приложения разные то всё ок.

Собственно вопрос, что за фигня происходит и как это можно чинить? А так же детектировать в автоматическом режиме ибо ничего не отваливается, а в консоль просто сыпятся сообщения вида?

X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Extension:    139 (RENDER)
  Minor opcode: 4 (RenderCreatePicture)
  Resource id:  0x7400005
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x7400005
X Error: RenderBadPicture (invalid Picture parameter) 143
  Extension:    139 (RENDER)
  Minor opcode: 7 (RenderFreePicture)
  Resource id:  0x1e0001f

ПС. Приложение делает скрины Dolphin'а

★★★★★

Последнее исправление: ya-betmen (всего исправлений: 2)

Ответ на: комментарий от i-rinat

Но здесь он сразу же копирует результат при помощи

QPixmap qpxmp = QPixmap::fromX11Pixmap(pixmap).copy();

А если XRenderComposite еще не отработал, то и результата не будет. Поэтому вроде как надо XSync вызвать. То есть не просто очередь на X-сервер сбросить, но и дождаться выполнения.

UPD. Или можно XSync после указанной строчки сделать до освобождения pixmap.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 2)
Ответ на: комментарий от Zubok

Логично. У меня были проблемы с созданием Picture после создания Pixmap, XFlush помог.

А ведь по идее это проблемы X сервера — синхронизация операций. В документации XRender про необходимость вызова XSync или XFlush вообще ничего не сказано.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Дело в том, что все рисовательные операции XRender (да и Core Protocol) не создают roundtrip, то есть они все не требуют ответа от X-сервера. Ты туда поток просто гонишь, а сервак рисует. Все рисовательные операции, которые происходят на X-сервере выполняются один за другим, но они буферизуются Xlib. Когда вдруг X-клиенту надо получить результат рисования назад к себе, то надо убедиться, что все отрисовалось, поэтому перед тем как получать результат надо сбросить оставшиеся запросы и долждаться окончания. Редко когда клиентам надо что-то из X-сервера забирать назад.

XFlush обычно используют, чтобы явно пнуть X-сервер дорисовать то, что еще в очереди ждет, но XFlush не ждет, дорисовалось или нет, а просто форсирует сброс буфера. Обычно XFlush вызывается неявно в XNextEvent и кое-каких еще функциях. XSync — это вообще чистый roundtrip. Обе эти функции даже не команды протокола X11, а именно управляющие функции Xlib. XSync вообще действует тупо. Посылает команду, которая ничего не делает (GetInputFocus) и ждет ответа именно не нее. Если ответ пришел, то все предыдущие уже выполнились.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)

Сделал проект демонстрирующий косяк(?): http://pastebin.com/jtCcRz9B.

А почему ты лезешь в иксы? У QPixmap есть метод QPixmap::grabWindow:

http://qt-project.org/doc/qt-4.8/qpixmap.html#grabWindow

UPD: А, я понял. Эта функция Qt перекрывающее окно тоже скопирует, что может быть нежелательным.

The grabWindow() function grabs pixels from the screen, not from the window, i.e. if there is another window partially or entirely over the one you grab, you get pixels from the overlying window, too.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 2)
Ответ на: комментарий от ya-betmen

Т.е. если я полезу к иксам из 2х разных потоков, то могу легко получить фигу?

Лезть к иксам через один Display * из нескольких потоков сразу — верный способ познать дзен. Или ад на земле. Тут уж как повезёт.

i-rinat ★★★★★
()
Ответ на: комментарий от Zubok

XSync вообще действует тупо. Посылает команду, которая ничего не делает (GetInputFocus) и ждет ответа именно не нее. Если ответ пришел, то все предыдущие уже выполнились.

Сурово. А то, что там пользователь может выцепить именно GetInputFocus из очереди игнорируя остальные?

sambist ★★
()
Ответ на: комментарий от i-rinat

Лезть к иксам через один Display * из нескольких потоков сразу — верный способ познать дзен. Или ад на земле. Тут уж как повезёт.

Проблем быть не должно, но лучше переходить на XCB. Она с самого начала была ориентирована на multithreading. Впрочем, в Xlib тоже есть поддержка. http://tronche.com/gui/x/xlib/display/XInitThreads.html. Но сейчас xlib уже переписана на базе xcb. По большому счету мы уже все xcb пользуемся опосредовано.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Угу, я вообще то надеялся на Kwin как на композитор, но оказалось что всё не так просто и за скринами надо лезть в иксы. А по ним практической инфы с гулькин нос.

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от sambist

Сурово. А то, что там пользователь может выцепить именно GetInputFocus из очереди игнорируя остальные?

Он там на номер ориентируется. Каждая команда имеет сквозной номер. Ответ на нее будет иметь тот же номер. Поэтому XSync ждет именно ответа на конкретный GetInputFocus, а чужие не тронет. В протоколе X11 нумерация идет.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от sambist

Таймаут стоит? А то я ведь и без обработки мессадж похерить могу.

Это как? Ты доступа туда не имеешь. XSync сам отправляет запрос и тут же ждет ответа.

XSync (
    register Display *dpy,
    Bool discard)
{
    xGetInputFocusReply rep;
    register xReq *req;

    LockDisplay(dpy);
    GetEmptyReq(GetInputFocus, req); <---- формируем запрос
    (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); <-- отсылаем и получаем ответ

    ...

    UnlockDisplay(dpy);
    return 1;
}

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok
while ((warehouse.halt != SML_FALSE) &&
       (XNextEvent(warehouse.screen.display, &event) >= 0))
    {
        switch (event.type)
        {
        case Expose          :          mainExpose(event); break;
        case FocusIn         :         mainFocusIn(event); break;
        case FocusOut        :        mainFocusOut(event); break;
        case KeyPress        :        mainKeyPress(event); break;
        case KeyRelease      :      mainKeyRelease(event); break;
        case ButtonPress     :     mainButtonPress(event); break;
        case ButtonRelease   :   mainButtonRelease(event); break;
        case EnterNotify     :     mainEnterNotify(event); break;
        case LeaveNotify     :     mainLeaveNotify(event); break;
        case ConfigureNotify : mainConfigureNotify(event); break;
        case ClientMessage   :   mainClientMessage(event); break;
        case MapNotify       :       mainMapNotify(event); break;
        case UnmapNotify     :     mainUnmapNotify(event); break;
        case MotionNotify    :    mainMotionNotify(event); break;
        default:                                           break;
        }
    }

Очередь на текущий момент: (внизу самые старые, FIFO)
5-MapNotify
4-KeyPress
3-KeyPress
2-KeyPress
1-KeyPress
0-EnterNotify

Вот ставит эта штука в конец FocusIn (или что во что там GetInputFocus развернется).

Вопрос - сообщения 0 - 5 будут: а) похерены, б) обработаны моими обработчиками?
Если б) то в каком обработчике у меня выскочит «лишний» вызов? Как разруливаются два бесконечных цикла: мой и тот, что в XSync?

Или его XGetInputFocus вообще не касается этой очереди?

sambist ★★
()
Последнее исправление: sambist (всего исправлений: 1)
Ответ на: комментарий от sambist

Это очередь *событий* (events), а не ответов! Ответы возвращаются как результаты работы функций у тех команд, которые его возвращают) :) Грубо говоря (упрощенно)

result = XGetInputFocus(...);

Вот к потоку ответов у пользователя нет доступа, все внутри xlib. События - это отдельный объект протокола. Есть запросы (с ответами) и события.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

XInitThreads

Должна быть первым вызовом. И всё равно приходётся оборачивать в Lock/Unlock. А если пишешь библиотеку, ни для первого, ни для второго гарантий нет.

переходить на XCB

Когда я смотрел в последний раз, были какие-то трудности с GLX.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

А если пишешь библиотеку, ни для первого, ни для второго гарантий нет.

Напротив. Если пишешь библиотеку - то сам контролируешь низкоуровневые вызовы.

sambist ★★
()
Ответ на: комментарий от sambist

Если пишешь библиотеку - то сам контролируешь низкоуровневые вызовы.

Тут путаница понятий. SDL, GTK, Qt — не библиотеки, а скорее фрейворки. Это в них находится инициализация и основной цикл приложения. А библиотека это нечто выполняющее отдельную задачу. Вроде растеризации шрифта.

Представь, что ты пишешь плагин для приложения. У меня это был плагин для плагина для плагина для браузера. Как из этой глубины попросить браузер при старте вызвать XInitThreads()? Не факт, что мой код вообще будет когда-либо вызван за время работы браузера.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Не факт, что мой код вообще будет когда-либо вызван за время работы браузера.

Даже если будет - XInitThreads надо вызывать вообще до всего. Да, я вас понял. Просто я никак не могу понять, как мне называть свой проект (библиотека? фреймворк?), наверное поэтому путаница.

sambist ★★
()
Ответ на: комментарий от sambist

Просто я никак не могу понять, как мне называть свой проект (библиотека? фреймворк?)

Если у тебя есть возможность заставить пользователя своего проекта вызывать что-то типа gtk_init() в начале своего main(), то у тебя фреймворк. Если твой проект можно использовать в написании плагина, который куда-то будет загружен, и в этом режиме он сможет выполнять свою работу, то это библиотека.

У меня вот сейчас есть потребность вызывать GTK функции из цикла сообщений Xlib, и это довольно мучительное заняние. Например, надо откуда-то взять GdkWindow и GdkEvent. Стандартных функций-обёрток над Xlib структурами в GTK не водится. Можно только наоборот, из GTK получить структуры Xlib.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Если у тебя есть возможность заставить пользователя своего проекта вызывать что-то типа gtk_init() в начале своего main(), то у тебя фреймворк.

SmlIndex win1;

int main(int argc, char * argv[])
{
    SmlInit());

    SmlWindowCreate(&win1);
    SmlWindowTitleSet(win1, "myTitle");
    SmlWindowSizeSet(win1, (SmlSize){800, 600});

    SmlEventAdd(win1, SML_EVENT_WINDOWDESTROY, wHDestroy);
    SmlEventAdd(win1, SML_EVENT_KEYPRESS,      wHKeyPress);

    SmlWindowVisibleSet(win1, SML_VISIBLE);

    SmlMain();

    return 0;
}

Считается за фреймворк?

sambist ★★
()
Ответ на: комментарий от Zubok

Спасибо, похоже что так.

Но блин, почему при гуглении по XRenderFreePicture я в результатах вижу патчи а не доки?

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Документация-то есть, но пока что не в виде man.

http://www.x.org/releases/X11R7.7/doc/libXrender/libXrender.txt

В любом случае, в иксах это общее правило: любой ресурс, который создается на сервере: window, pixmap, picture, glyphs, glyphset, colormap, GC, Cursor, и т. д. должен быть когда-то особожден. Всегда есть соответствующий Free и Destroy.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от i-rinat

через один Display * из нескольких потоков

А что, свой mutex разве не поможет? Сидишь в своем потоке, дела делаешь, а второй подождет чутка, не?

deep-purple ★★★★★
()

Я еще раз глянул код. Вопросы есть. А зачем вообще создавать picture? И зачем XRenderComposite в принципе? Почему ты сразу pixmap, полученный из XCompositeNameWindowPixmap не копируешь в QPixmap?

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Наверное потому, что я плохо представляю как работает эта фигня, поэтому остановился на самом первом рабочем варианте, который скомпилировал из исходников, которые нарыл в интернете. Попробую упростить.

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Там и другие ошибки вроде есть, которые, скорее всего и привели к тому, что отображается фигня. В XRenderComposite ты наоборот рисуешь из пустой picture в pixmap с изображением окна. У тебя аргументы src и dst перепутаны в функции. Когда у тебя создается picture какая-то прозрачная, то тогда у тебя pixmap не меняется. Просто везет. Но есть случаи, когда у тебя picture создается в области, где все залито цветом без прозрачности. Когда ты делаешь XRenderComposite, то у тебя pixmap окна зарисовывается фигней.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Спасибо, попробую пофиксить. Если ты с иксами на короткой ноге может подскажешь какую-нибудь книжку/статью, желательно с простыми примерами для базовых юзкейсов, потому что с нуля (мой текущий уровень) тяжело вникнуть, а то я примеры использования методов в сырцах смотрю (kwin и прочее).

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Спасибо, попробую пофиксить.

Только напиши тут, что получается (или не получается). Только фиксить, как мне кажется, не стоит. Надо сразу попробовать pixmap в QPixmap копировать, а все эти XRender* закомментировать.

может подскажешь какую-нибудь книжку/статью, желательно с простыми примерами для базовых юзкейсов, потому что с нуля (мой текущий уровень) тяжело вникнуть,

Не-а, не посоветую. :) Документация проекта X.org, интернет, чужой код. Для понимания арихитектуры и как все работает тоже достаточно интернета. Если ты используешь Qt, то иксами лучше себе голову не забивать. А если решаешь какую-то очень специфичную задачу, где это надо, то можно и спросить, а потом доразобраться самостоятельно

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 3)
Ответ на: комментарий от deep-purple

А что, свой mutex разве не поможет?

Поможет.

В моём случае приложение передавало Display*, который было бесполезно оборачивать mutex'ами: даже если я сериализую вызовы, приложение такой гарантии не предоставляет. Решением было открывать своё соединение с X сервером. Ну и mutex'ы, да.

Там есть ещё сюрприз. Вызовы OpenGL типа glClear() могут под капотом обращаться к X серверу, так что их тоже надо оборачивать в блокировки.

i-rinat ★★★★★
()
Ответ на: комментарий от Zubok

Только напиши тут, что получается (или не получается).

Обязательно.

Документация проекта X.org, интернет, чужой код. Для понимания арихитектуры и как все работает тоже достаточно интернета

Ну так туда и смотрю

Если ты используешь Qt, то иксами лучше себе голову не забивать. А если решаешь какую-то очень специфичную задачу, где это надо, то можно и спросить, а потом доразобраться самостоятельно

Гуй на Qt, но с ним и своими силами могу разобраться. Просто количество и качество инфы особенно начального уровня по иксам и кутям просто несравнимо.

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от Zubok

а все эти XRender* закомментировать.

Действительно, работает, метод теперь такой:

QPixmap makeScreenshot(XID xid, Display *display){
    int event_base_return;
    int error_base_return;
    if (XCompositeQueryExtension (display, &event_base_return, &error_base_return)){
        //std::cout << "COMPOSITE IS ENABLED!\n";
    }
    XFlush(display);
    XCompositeRedirectWindow (display, xid, CompositeRedirectAutomatic);
    Pixmap pixmap = XCompositeNameWindowPixmap (display, xid);
    XWindowAttributes attr;
    Status s = XGetWindowAttributes (display, xid, &attr);
    if (s == 0){
        std::cout << "Fail to get window attributes!\n";
    }
    QPixmap qpxmp = QPixmap::fromX11Pixmap(pixmap).copy();
    XSync(display, false);
    XFreePixmap (display, pixmap);
    XCompositeUnredirectWindow (display, xid, CompositeRedirectAutomatic);
    return qpxmp;
}

Только я не понимаю, почему если я убираю вызов XGetWindowAttributes или делаю его до XCompositeNameWindowPixmap то всё перестаёт работать?

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Это все можно убрать тоже. Никак же не используются атрибуты. Лишний код.

    XWindowAttributes attr;
    Status s = XGetWindowAttributes (display, xid, &attr);
    if (s == 0){
        std::cout << "Fail to get window attributes!\n";
    }

Вот в таком виде работает? Попробуй XSync() поставить вместо этого вызова, а не после QPixmap. А что значит, что перестает работать? Вообще изображения нет?

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

Я смотрю в исходники Qt на их сайте. Qt вроде бы XRender*, XGetWindowAttributes сам вызывает и все копирования выполняет.

Вот fromX11Pixmap(), а вот copy()

Получается, что XSync() перед qpxmp = QPixmap... как бы бессмысленный, так как XGetGeometry, XGetWindowAttributes в коде qpixmap_x11.cpp это уже запросы с ответом и автоматом делают то, что делает XSync(). Поэтому если действительно наличие или отсутсвие XGetWindowAttributes в твоем коде влияет на результат, то получается, что иксы не успевают подготовить картинку окна в pixmap, а твоя XGetWindowAttributes задержку формировала. Вот надо выяснить симптомы.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 4)
Ответ на: комментарий от Zubok

Спасибо, XSync вместо XGetWindowAttributes помог. Перестаёт работать означало практически черную картинку и ошибки типа X Error Bad Drawable.

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от Zubok

Хм, тогда вероятно последняя картинка могла засираться тоже из-за нехватки времени.

ya-betmen ★★★★★
() автор топика
Последнее исправление: ya-betmen (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

Спасибо, XSync вместо XGetWindowAttributes помог. Перестаёт работать означало практически черную картинку и ошибки типа X Error Bad Drawable.

А с XSync нет ошибок? А можешь показать, какую ошибку он пишет без XSync?

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Убираю XSync

QPixmap makeScreenshot(XID xid, Display *display){
    int event_base_return;
    int error_base_return;
    if (XCompositeQueryExtension (display, &event_base_return, &error_base_return)){
        //std::cout << "COMPOSITE IS ENABLED!\n";
    }
    XFlush(display);
    XCompositeRedirectWindow (display, xid, CompositeRedirectAutomatic);
    Pixmap pixmap = XCompositeNameWindowPixmap (display, xid);
    QPixmap qpxmp = QPixmap::fromX11Pixmap(pixmap).copy();
    XFreePixmap (display, pixmap);
    XCompositeUnredirectWindow (display, xid, CompositeRedirectAutomatic);
    return qpxmp;
}

Получаю ошибки следующего типа:

113246226 = CMakeLists.txt ? Kate
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 14 (X_GetGeometry)
  Resource id:  0x74000e8
X Error: BadWindow (invalid Window parameter) 3
  Major opcode: 3 (X_GetWindowAttributes)
  Resource id:  0x12f60c8
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Extension:    139 (RENDER)
  Minor opcode: 4 (RenderCreatePicture)
  Resource id:  0x74000e8
X Error: RenderBadPicture (invalid Picture parameter) 143
  Extension:    139 (RENDER)
  Minor opcode: 7 (RenderFreePicture)
  Resource id:  0x74000e8

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Очень странно все. Получается, что после отработки XCompositeNameWindowPixmap и *получения ответа* от него, pixmap (его XID) еще не создан, но XID уже возвращен. X_GetGeomenty и т. д. - это уже QPixmap вызывает (код выше). И почему-то он считает его BadDrawable сразу , а после XSync не считает.

Попробуй тупо в цикле запускать. Посмотри, ошибки типа этих, но с XSync() появляются? А я попробую разобраться. Но только не сразу.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Попробуй тупо в цикле запускать.

Ну оно у меня по списку окон и так в цикле вертится. Если воткнуть цикл в метод то начинают падать ошибки уже при 2х итерациях, правда если закоментить XFreePixmap то ошибки пропадают.

QPixmap makeScreenshot(XID xid, Display *display){
    QPixmap qpxmp;
    XCompositeRedirectWindow (display, xid, CompositeRedirectAutomatic);
    for (int i = 0; i < 100; i++){
        XFlush(display);
        Pixmap pixmap = XCompositeNameWindowPixmap (display, xid);
        XSync(display, false);
        qpxmp = QPixmap::fromX11Pixmap(pixmap).copy();
        XFreePixmap (display, pixmap);//<-- закомментировать тут
    }
    XCompositeUnredirectWindow (display, xid, CompositeRedirectAutomatic);
    return qpxmp;
}

А может ты знаешь как можно получить скриншот каким-то более простым способом, мне не принципиально что б через xlib?

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от sambist

Кажется, понятно. XID создается в xlib и передается как параметр в запрос CompositeNameWindowPixmap. Сам этот запрос не имеет ответа вообще, то есть резервирование памяти pixmap и запись туда происходит асинхронно с клиентской программой. То есть надо ждать, когда pixmap отрисуется.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Это где-то задокументировано? Просто получается, что нет механизма, который позволяет отмерить время «ровно до инициализации», чтобы дальше можно было работать уже с валидным ID. Попахивает неправильным проектированием. Подозреваю, что если написать в багзиллу, будет помечено как WONTFIX.

sambist ★★
()
Ответ на: комментарий от ya-betmen

А может ты знаешь как можно получить скриншот каким-то более простым способом, мне не принципиально что б через xlib?

Через xlib - только XGetImage (но он возвратит не pixmap, а XImage, то есть твоему клиенту дамп пригонит!) и XCopyArea (копирует из одного Drawable в другой, в частности в Pixmap, на стороне X-сервера). Последнее и делает QPixmap.grabWindow, но это не то, что ты хочешь. И XGetImage не то. Это никак не позволит получить тебе off-screen buffer у окна, который как раз редиректом в CompositeExtension создается.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от sambist

Надо разобраться. Вероятно, по исходному коду. Пока не ясен вопрос, в какой момент pixmap уже можно пользоваться. К сожалению, ни разу не приходилось иметь дело с X Composite Extension.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Поковырял kwin, там есть асинхронный dbus интерфейс получения скриншота указанного окна, думал они дожидаются результата от иксов, но он точно так же глючит. Если запрашивать в цикле, то в ответ может прийти кривой пиксмап.

ya-betmen ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Я все-таки думаю, что надо заводить багу. Ибо это недоработка, так как цепляет вполне реальный код из kwin.

sambist ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.