c++ - 创建带有帧缓冲区的 xlib 窗口,我可以直接绘制并使用 XPutImage

标签 c++ c codeblocks x11 xlib

我正在尝试创建一个 xlib 窗口,创建一个深度为 32 的帧缓冲区并将该缓冲区绘制到窗口,但是。一切正常,直到 XPutImage 被调用,窗口永远不会显示并且控制台输出:

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

如果我在 Expose 事件中注释掉 XPutImage 行,那么我会得到一个具有所需透明客户区的窗口。所以我正在寻找如何解决这个问题的答案。

注意我是 Linux 编程新手,但已经进行 Windows 编程很长时间了。所以我对 Linux 功能和协议(protocol)还不熟悉;)

我在 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, 100, width, height, 0, depth, InputOutput,
                        visual, CWBackPixel | CWColormap | CWBorderPixel, &attrs);

    ximage = XCreateImage(dpy, vinfo.visual, 32, XYPixmap, 0, (char *)framebuf, width, height, 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, parent, gcm, &gcv);

    XMapWindow(dpy, win);

    while(!XNextEvent(dpy, &event))
    {
        switch(event.type)
        {
        case Expose:
            printf("I have been exposed!\n");
            XPutImage(dpy, win, NormalGC, ximage, 0, 0, 0, 0, width, 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, XDefaultScreen(dpy), 24, TrueColor, &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, 100, width, height, 0, depth, InputOutput,
                        visual, CWBackPixel | CWColormap | CWBorderPixel, &attrs);

    //Change to this line
    //ximage = XCreateImage(dpy, vinfo.visual, 32, XYPixmap, 0, (char *)framebuf, width, height, 8, width*4);
    ximage = XCreateImage(dpy, vinfo.visual, depth, ZPixmap, 0, (char *)framebuf, width, height, 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, parent, gcm, &gcv);

    XMapWindow(dpy, win);

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

    printf("No error\n");

    return 0;
}

关于c++ - 创建带有帧缓冲区的 xlib 窗口,我可以直接绘制并使用 XPutImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64521652/

相关文章:

ubuntu - 从代码块打印后记 - 非常奇怪的输出

c++ - 无法访问派生类中的基本 protected 成员! (在虚函数中)

c - "overlapping"功能的良好库设计

c++ - Visual C++ native 内存管理最佳实践

c - 为什么需要在 C 中的字符串数组中声明字符串的长度?

c - 正确的方法是使用位域以二进制形式打印数字

c++ - 在 C++ Win32 中哪个 Windows SDK 最适合我?

C - 使用自由函数时程序崩溃

c# - 调用从 C# 获取字符指针的 C++ 函数

c++ - 使用 "branchy"开发模型避免不必要的重新编译