使用框架缓冲区创建xlib窗口,我可以直接绘制并使用XPutImage

问题描述

我试图创建一个xlib窗口,创建一个深度为32的帧缓冲区,然后将该缓冲区绘制到窗口上。一切正常,直到调用XPutImage,窗口永不显示且控制台输出为止:

Process returned -1 (0xFFFFFFFF) execution time : ?.??? s
Press ENTER to continue;

如果我在Expose事件中注释掉XPutImage行,那么我会得到一个窗口,该窗口具有所需的透明工作区。因此,我正在寻找解决方法。

注意我是Linux编程的新手,但是从事Windows编程已有很长时间了。所以我还不熟悉Linux函数和协议;)

我在Fedora 32(64位)上使用Code :: Blocks 20.03。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>

int main(int argc,char **argv)
{
    Display *dpy;
    XVisualInfo vinfo;
    int depth;
    XVisualInfo *visual_list;
    XVisualInfo visual_template;
    int nxvisuals;
    int i;
    XSetWindowAttributes attrs;
    Window parent;
    Visual *visual;

    int width,height;
    Window win;
    int *framebuf;
    XImage *ximage;
    XEvent event;

    dpy = XOpenDisplay(NULL);

    nxvisuals = 0;
    visual_template.screen = DefaultScreen(dpy);
    visual_list = XGetVisualInfo (dpy,VisualScreenMask,&visual_template,&nxvisuals);

    for (i = 0; i < nxvisuals; ++i)
    {
        printf("  %3d: visual 0x%lx class %d (%s) depth %d\n",i,visual_list[i].visualid,visual_list[i].class,visual_list[i].class == TrueColor ? "TrueColor" : "unknown",visual_list[i].depth);
    }

    if (!XMatchVisualInfo(dpy,XDefaultScreen(dpy),32,TrueColor,&vinfo))
    {
        fprintf(stderr,"no such visual\n");
        return 1;
    }

    printf("Matched visual 0x%lx class %d (%s) depth %d\n",vinfo.visualid,vinfo.class,vinfo.class == TrueColor ? "TrueColor" : "unknown",vinfo.depth);

    parent = XDefaultRootWindow(dpy);

    XSync(dpy,True);

    printf("creating RGBA child\n");

    visual = vinfo.visual;
    depth = vinfo.depth;

    attrs.colormap = XCreateColormap(dpy,XDefaultRootWindow(dpy),visual,AllocNone);
    attrs.background_pixel = 0;
    attrs.border_pixel = 0;

    width = 1000;
    height = 700;

    framebuf = malloc((width*height)*4);

    for (i = 0; i < (width*height); i++)
    {
        framebuf[i] = 0xFFFFFFFF;
    }

    win = XCreateWindow(dpy,parent,100,width,height,depth,InputOutput,CWBackPixel | CWColormap | CWBorderPixel,&attrs);

    ximage = XCreateImage(dpy,vinfo.visual,XYPixmap,(char *)framebuf,8,width*4);

    if (ximage == 0)
    {
        printf("ximage is null!\n");
    }

    XSync(dpy,True);

    XSelectInput(dpy,win,ExposureMask | KeyPressMask);

    XGCValues gcv;
    unsigned long gcm;
    GC NormalGC;

    //gcm = GCForeground | GCBackground | GCGraphicsExposures;
    //gcv.foreground = BlackPixel(dpy,parent);
    //gcv.background = WhitePixel(dpy,parent);
    gcm = GCGraphicsExposures;
    gcv.graphics_exposures = 0;
    NormalGC = XCreateGC(dpy,gcm,&gcv);

    XMapWindow(dpy,win);

    while(!XNextEvent(dpy,&event))
    {
        switch(event.type)
        {
        case Expose:
            printf("I have been exposed!\n");
            XPutImage(dpy,NormalGC,ximage,height);
            break;
        }
    }

    printf("No error\n");

    return 0;
}

解决方法

要使其正常工作,我必须在代码中更改两行。您可能不会满意,因为要使其正常工作,我必须将其从RGBA更改为BGRX。每当我使用xlib时,即使数据以32位存储,我也总是必须使用24位深度。它也存储为BGRX而不是RGBX ...

这是更改后的代码。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>

int main(int argc,char **argv)
{
    Display *dpy;
    XVisualInfo vinfo;
    int depth;
    XVisualInfo *visual_list;
    XVisualInfo visual_template;
    int nxvisuals;
    int i;
    XSetWindowAttributes attrs;
    Window parent;
    Visual *visual;

    int width,height;
    Window win;
    int *framebuf;
    XImage *ximage;
    XEvent event;

    dpy = XOpenDisplay(NULL);

    nxvisuals = 0;
    visual_template.screen = DefaultScreen(dpy);
    visual_list = XGetVisualInfo (dpy,VisualScreenMask,&visual_template,&nxvisuals);

    //Change to this line
    //if (!XMatchVisualInfo(dpy,XDefaultScreen(dpy),32,TrueColor,&vinfo))
    if (!XMatchVisualInfo(dpy,24,&vinfo))
    {
        fprintf(stderr,"no such visual\n");
        return 1;
    }

    parent = XDefaultRootWindow(dpy);

    XSync(dpy,True);

    printf("creating RGBA child\n");

    visual = vinfo.visual;
    depth = vinfo.depth;

    attrs.colormap = XCreateColormap(dpy,XDefaultRootWindow(dpy),visual,AllocNone);
    attrs.background_pixel = 0;
    attrs.border_pixel = 0;

    width = 1000;
    height = 700;

    framebuf = (int *) malloc((width*height)*4);

    for (i = 0; i < (width*height); i++)
    {
        framebuf[i] = 0xFF00FFFF;
    }

    win = XCreateWindow(dpy,parent,100,width,height,depth,InputOutput,CWBackPixel | CWColormap | CWBorderPixel,&attrs);

    //Change to this line
    //ximage = XCreateImage(dpy,vinfo.visual,XYPixmap,(char *)framebuf,8,width*4);
    ximage = XCreateImage(dpy,ZPixmap,width*4);

    if (ximage == 0)
    {
        printf("ximage is null!\n");
    }

    XSync(dpy,True);

    XSelectInput(dpy,win,ExposureMask | KeyPressMask);

    XGCValues gcv;
    unsigned long gcm;
    GC NormalGC;

    //gcm = GCForeground | GCBackground | GCGraphicsExposures;
    //gcv.foreground = BlackPixel(dpy,parent);
    //gcv.background = WhitePixel(dpy,parent);
    gcm = GCGraphicsExposures;
    gcv.graphics_exposures = 0;
    NormalGC = XCreateGC(dpy,gcm,&gcv);

    XMapWindow(dpy,win);

    while(!XNextEvent(dpy,&event))
    {
        switch(event.type)
        {
        case Expose:
            printf("I have been exposed!\n");
            XPutImage(dpy,NormalGC,ximage,height);
            break;
        }
    }

    printf("No error\n");

    return 0;
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...