X11: невозможно нарисовать изображение в прозрачном окне, созданном с помощью XCreateWindow - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь создать простое окно X11, в котором должен отображаться файл PNG с прозрачными областями. Я хочу, чтобы у самого окна не было (непрозрачного) фона, чтобы прозрачные области в PNG отображали то, что находится за окном.

tl; dr Я не могу поместить изображение на полу- прозрачное окно; он дает «Плохое совпадение».

Я могу успешно создать полупрозрачное окно с помощью XCreateWindow и XMatchVisualInfo:

XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), 
        vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent

Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
        width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
        CWColormap | CWBorderPixel | CWBackPixel, &attr);

(Полный исходный код ниже)

Затем я создаю изображение, используя:

// "image32" is a generated image - see source code below
XImage *ximage = XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
        ZPixmap, 0, image32, width, height, 32, 0);

И отображаю изображение во время события Expose:

XPutImage(display, window, DefaultGC(display, 0), ximage,
        0, 0, 0, 0, width, height);

Я компилирую с gcc test.c -L/usr/X11R6/lib -lX11 -lXrandr -o test и запустить с ./test:

X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  72 (X_PutImage)
  Serial number of failed request:  11
  Current serial number in output stream:  12

Примечание: Если я заменю строки, создающие окно (XCreateWindow), на эти:

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

Он отображает окно правильно; однако прозрачности нет.

Я прочитал документы о XCreateWindow , XPutImage , XCreateImage и попытался поиграть с несколькими параметрами, но безуспешно .

Я прочитал этот вопрос SO и попытался поиграть с глубиной цвета; поскольку документы, в которых упоминается «Плохое совпадение», также могут быть выброшены из-за неправильного изображения, я проверил, что один и тот же визуальный элемент был отправлен во все места в моем коде.

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

Спасибо !

Полный исходный код:

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

// Window size
int height = 256, width = 256;

XImage *CreateTrueColorImage(Display *display, Visual *visual)
{

    int i, j;
    unsigned char *image32=(unsigned char *)malloc(width*height*4);
    unsigned char *p=image32;
    for(i=0; i<width; i++)
    {
        for(j=0; j<height;j++)
        {
            *p++ = i;
            *p++ = i;
            *p++ = j;
            *p++ = j; // alpha channel (should progressively get transparent towards left)
        }
    }

    // Replacing "DefaultDepth(display,DefaultScreen(display))" with a hardcoded 
    // 24 or 32 still doesn't work with XCreateWindow. XCreateSimpleWindow works
    // with hardcoded 24, but not 32.
    return XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
            ZPixmap, 0, image32, width, height, 32, 0);
}

int main(int argc, char **argv)
{
    XImage *ximage;
    Display *display = XOpenDisplay(NULL);
    Visual *visual = DefaultVisual(display, 0);

    XVisualInfo vinfo;
    XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);

    XSetWindowAttributes attr;
    attr.colormap = XCreateColormap(display, DefaultRootWindow(display), 
            vinfo.visual, AllocNone);
    attr.border_pixel = 0;
    attr.background_pixel = 0x80800000; // Red, semi-transparent

    //Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
    //      width, height, 1, 0, 0);
    Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
            width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
            CWColormap | CWBorderPixel | CWBackPixel, &attr);

    ximage = CreateTrueColorImage(display, vinfo.visual);
    XSelectInput(display, window, ButtonPressMask|ExposureMask);
    XMapWindow(display, window);

    while(1)
    {
        XEvent event;
        XNextEvent(display, &event);
        switch(event.type)
        {
        case Expose:
            XPutImage(display, window, DefaultGC(display, 0), ximage,
                    0, 0, 0, 0, width, height);
            break;
        case ButtonPress:
            exit(0);
        }
    }
}

1 Ответ

1 голос
/ 11 мая 2020

Мне удалось заставить его работать, сделав два изменения. Во-первых, вместо использования DefaultGC(display, 0) вы должны создать G C для вашего окна c.

GC gc = XCreateGC(display, window, 0, 0);

При этом, если вы жестко закодируете глубину XCreateImage до 32, она должна работать правильно . И вы также можете использовать глубину, предоставленную XVisualInfo, например,

XCreateImage(display, vinfo.visual, vinfo.depth,
        ZPixmap, 0, image32, width, height, 32, 0);
...