我不明白 Xwindows 中字体的行为

I don't understand the behavior of fonts in Xwindows

给定示例程序:

/*
 * Study for multiple windows.
 */
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {

    Window       w1, w2;
    XEvent       e;
    const char*  msg1 = "Hello, window 1";
    const char*  msg2 = "Hello, window 2";
    int          s1;
    int          s2;
    GC           gracxt1;
    GC           gracxt2;
    XFontStruct* font;
    XFontStruct* font2;
    Display* d1;
    Display* d2;
 
    d1 = XOpenDisplay(NULL);
    if (d1 == NULL) {

        fprintf(stderr, "Cannot open display\n");
        exit(1);

    }
printf("d1: %p\n", d1);

    d2 = XOpenDisplay(NULL);
    if (d2 == NULL) {

        fprintf(stderr, "Cannot open display\n");
        exit(1);

    }
printf("d2: %p\n", d2);
 
    s1 = DefaultScreen(d1);
    s2 = DefaultScreen(d1);
printf("s1: %d\n", s1);
printf("s2: %d\n", s2);
    gracxt1 = XDefaultGC(d1, s1);
#if 0
    gracxt2 = XDefaultGC(d2, s2);
#else
    gracxt2 = XDefaultGC(d1, s2);
#endif

    font = XLoadQueryFont(d1,
        "-bitstream-courier 10 pitch-bold-r-normal--0-0-200-200-m-0-iso8859-1");
    if (!font) {

        fprintf(stderr, "*** No font ***\n");
        exit(1);

    }
    XSetFont(d1, gracxt1, font->fid);

    font2 = XLoadQueryFont(d1,
            "-bitstream-courier 10 pitch-bold-r-normal--0-0-400-400-m-0-iso8859-1");
    if (!font2) {

        fprintf(stderr, "*** No font ***\n");
        exit(1);

    }
    XSetFont(d1, gracxt2, font2->fid);

    w1 = XCreateSimpleWindow(d1, RootWindow(d1, s1), 10, 10, 640, 480, 5,
                            BlackPixel(d1, s1), WhitePixel(d1, s1));
    XSelectInput(d1, w1, ExposureMask|KeyPressMask|PointerMotionMask|StructureNotifyMask);
    XMapWindow(d1, w1);

    w2 = XCreateSimpleWindow(d1, RootWindow(d1, s1), 10, 10, 640, 480, 5,
                            BlackPixel(d1, s2), WhitePixel(d1, s2));
    XSelectInput(d1, w2, ExposureMask|KeyPressMask|PointerMotionMask|StructureNotifyMask);
    XMapWindow(d1, w2);

    while (1) {

        XNextEvent(d1, &e);
        if (e.type == Expose) {

            if (e.xany.window == w1) XDrawString(d1, e.xany.window, gracxt1, 10, 50, msg1, strlen(msg1));
            else XDrawString(d1, e.xany.window, gracxt2, 10, 50, msg2, strlen(msg2));

        }
        if (e.type == KeyPress) break; /* exit on any key */

    }

    XCloseDisplay(d1);
    XCloseDisplay(d2);

    return 0;

}

设置两个windows和select两种不同的字体,window各一种,然后打印。我对 XWindows 的理解是字体被 selected 到图形上下文中,即 GC。但是,根据使用的 Display*,我会得到两种不同的行为:

#if 1

IE,每个 window 具有不同大小的字体,或者:

#if 0

我认为,并且文档强烈暗示,字体是通过 XSetFont() 调用 selected 到上下文 gracxt1 或 gracxt2 的。因此,我从两个 GC 开始这个示例,但一个 Display* 和一个屏幕 select。但是,在我为每个 window 赋予其自己的 Display*.

之前,我没有得到每个 window 的字体 select 的行为

打印显示:

d1: 0x55a5694692a0 d2: 0x55a569477170 s1: 0 s2: 0

对于两者,不同的 Display* 但相同的屏幕索引。那么 window 的字体 select 存储在哪里呢?显示器*?

文档说“字体 selected 到 GC,显示仅指定与 X 服务器的连接”。

OS: Ubuntu 20.04

我打印了每个 gracxt1 和 gracxt2 的 GContext 编号:

#if 1(工作案例)

d1: 0x55b4ae3d82a0
d2: 0x55b4ae3e6170
s1: 0
s2: 0
GCContext 1: 69206016
GCContext 2: 71303168

#if 0(失败案例)

d1: 0x55b4149672a0
d2: 0x55b414975170
s1: 0
s2: 0
GCContext 1: 69206016
GCContext 2: 69206016

为正常运行而重构的程序:

/*
 * Study for multiple windows.
 */
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {

    Window       w1, w2;
    GC           gracxt1, gracxt2;
    XEvent       e;
    const char*  msg1 = "Hello, window 1";
    const char*  msg2 = "Hello, window 2";
    int          s;
    XFontStruct* font;
    Display* d;
 
    d = XOpenDisplay(NULL);
    if (d == NULL) {

        fprintf(stderr, "Cannot open display\n");
        exit(1);

    }
 
    s = DefaultScreen(d);
    s = DefaultScreen(d);

    w1 = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 640, 480, 5,
                            BlackPixel(d, s), WhitePixel(d, s));
    XSelectInput(d, w1, ExposureMask|KeyPressMask|PointerMotionMask|StructureNotifyMask);
    XMapWindow(d, w1);
    gracxt1 = XCreateGC(d, w1, 0, NULL);

    w2 = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 640, 480, 5,
                            BlackPixel(d, s), WhitePixel(d, s));
    XSelectInput(d, w2, ExposureMask|KeyPressMask|PointerMotionMask|StructureNotifyMask);
    XMapWindow(d, w2);
    gracxt2 = XCreateGC(d, w2, 0, NULL);

    font = XLoadQueryFont(d,
        "-bitstream-courier 10 pitch-bold-r-normal--0-0-200-200-m-0-iso8859-1");
    if (!font) {

        fprintf(stderr, "*** No font ***\n");
        exit(1);

    }
    XSetFont(d, gracxt1, font->fid);

    font = XLoadQueryFont(d,
            "-bitstream-courier 10 pitch-bold-r-normal--0-0-400-400-m-0-iso8859-1");
    if (!font) {

        fprintf(stderr, "*** No font ***\n");
        exit(1);

    }
    XSetFont(d, gracxt2, font->fid);

    while (1) {

        XNextEvent(d, &e);
        if (e.type == Expose) {

            if (e.xany.window == w1) XDrawString(d, e.xany.window, gracxt1, 10, 50, msg1, strlen(msg1));
            else XDrawString(d, e.xany.window, gracxt2, 10, 50, msg2, strlen(msg2));

        }
        if (e.type == KeyPress) break; /* exit on any key */

    }

    XCloseDisplay(d);

    return 0;

}

字体是图形上下文的一部分。每个图形上下文都有自己独立的字体设置。

我认为您的 post 扭转了 #if 0#if 1 案例的行为。如果是这样,那么您描述的行为就很有意义了。

XOpenDisplay creates one graphics context per screen after connecting to the server. 所以 d1 有屏幕 0 的图形上下文,而 d2 有屏幕 0 的单独图形上下文。因此:

  • 在这两种情况下,gracxt1 使用 d1 屏幕 0 的图形上下文。

  • #if 0情况下,gracxt2使用d2屏幕0的图形上下文,与分开 gracxt1。您将每个 GC 的字体设置为不同的值。这是我们在您的第一个屏幕截图中看到的行为:两个 GC 具有不同的字体。

  • #if 1情况下,gracxt2使用d1屏幕0的图形上下文,与相同[=48] =] gracxt1。当你设置gracxt2的字体时,你也在设置了gracxt1的字体,覆盖了之前的设置(因为它们是同一个GC)。这是我们在您的第二个屏幕截图中看到的行为。