You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xlib窗口背景Pixmap镜像反转问题求助

Xlib设置窗口背景Bitmap时图案镜像反转的原因分析

问题描述

我在用Xlib给窗口设置背景Bitmap时,出现了图案镜像反转的问题——每个方块的阴影本该在左上角,实际却显示在右上角。用注释里的棋盘格Bitmap数据时显示正常,但当前带阴影的方块图案就会反转,求原因?

复现代码

// test1.c
// compile command: gcc -o test1 test1.c -lX11

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

#define backing_width   16
#define backing_height  16

/*
static unsigned char backing_bits[] = {
    0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 
    0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 
    0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff
};
*/

static unsigned char backing_bits[] = {
    0xBF, 0xBF, 0x00, 0x00, 0xBF, 0xBF, 0xBF, 0xBF, 0xB0, 0xB0, 0xB0, 0xB0,
    0xB0, 0xB0, 0xB0, 0xB0, 0xBF, 0xBF, 0x00, 0x00, 0xBF, 0xBF, 0xBF, 0xBF,
    0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0
};

int main (int argc, char *argv[]) {
    Display                 *mydisplay;
    XSetWindowAttributes    myat;
    Window                  mywindow;
    XSizeHints              wmsize;
    XWMHints                wmhints;
    XTextProperty           windowName, iconName;
    XEvent                  myevent;
    char                    *window_name = "Test";
    char                    *icon_name = "Te";
    int                     screen_num, done;
    unsigned long           valuemask;
    Pixmap                  back;

    mydisplay = XOpenDisplay("");

    screen_num = DefaultScreen(mydisplay);
    myat.background_pixel = WhitePixel(mydisplay, screen_num);
    myat.border_pixel = BlackPixel(mydisplay, screen_num);
    myat.event_mask = ButtonPressMask;
    valuemask = CWBackPixel | CWBorderPixel | CWEventMask;
    mywindow = XCreateWindow(mydisplay, RootWindow(mydisplay, screen_num),
                            200, 300, 350, 250, 2,  // x, y, height, width, border width
                            DefaultDepth(mydisplay, screen_num), InputOutput,
                            DefaultVisual(mydisplay, screen_num),
                            valuemask, &myat);
    back = XCreatePixmapFromBitmapData(mydisplay, mywindow,
                            backing_bits, backing_width, backing_height,
                            BlackPixel(mydisplay, screen_num),
                            WhitePixel(mydisplay, screen_num),
                            DefaultDepth(mydisplay, screen_num));
    XSetWindowBackgroundPixmap(mydisplay, mywindow, back);

    wmsize.flags = USPosition | USSize;
    XSetWMNormalHints(mydisplay, mywindow, &wmsize);
    wmhints.initial_state = NormalState;
    wmhints.flags = StateHint;
    XSetWMHints(mydisplay, mywindow, &wmhints);
    XStringListToTextProperty(&window_name, 1, &windowName);
    XSetWMName(mydisplay, mywindow, &windowName);
    XStringListToTextProperty(&icon_name, 1, &iconName);
    XSetWMIconName(mydisplay, mywindow, &iconName);

    XMapWindow(mydisplay, mywindow);

    done = 0;
    while (done == 0) {
        XNextEvent(mydisplay, &myevent);
        switch (myevent.type) {
            case ButtonPress:
                done = 1;
                break;
        }
    }

    XUnmapWindow(mydisplay, mywindow);
    XDestroyWindow(mydisplay, mywindow);
    XCloseDisplay(mydisplay);
}

效果对比

  • 预期效果:每个带阴影的方块,阴影位于方块左上角,光影方向符合视觉习惯。
  • 实际效果:每个带阴影的方块,阴影位于方块右上角,整体图案呈现垂直镜像反转的状态。

原因分析与解决方案

核心原因

Xlib的Bitmap数据存储规则是按行从下到上排列,但你定义的backing_bits是按从上到下的顺序编写的,导致渲染时整个图案上下颠倒。因为棋盘格是上下对称的图案,颠倒后视觉无变化,所以之前测试时没发现问题;而带阴影的方块是非对称图案,上下颠倒后阴影位置就明显反转了。

解决方案

将backing_bits数组的行顺序反转,把原本的最后一行移到最前面,依次类推即可修正。

以你当前的16x16 Bitmap为例,每行占用2字节,原数组的行顺序是第0行到第15行,需要调整为第15行、第14行……第0行的顺序。

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 23:13:17