16

以下代码如何删除窗口边框?

//note the struct is declared elsewhere, is here just for clarity.
//code is from [http://tonyobryan.com/index.php?article=9][1]
typedef struct Hints
{
    unsigned long   flags;
    unsigned long   functions;
    unsigned long   decorations;
    long            inputMode;
    unsigned long   status;
} Hints;

//code to remove decoration
Hints hints;
Atom property;
hints.flags = 2;
hints.decorations = 0;
property = XInternAtom(display, "_MOTIF_WM_HINTS", true);
XChangeProperty(display,window,property,property,32,PropModeReplace,(unsigned char *)&hints,5);
XMapWindow(display, window);

到目前为止,我已经收集到 Atom 是一种类似于 Window 和 Display 的标识符,但我无法弄清楚 Hints 结构或“_MOTIF_WM_HINTS”的来源。谁能为我解释所有这些代码?提前谢谢,嗯。

4

2 回答 2

16

很难通过任何形式的“官方”外观标准或类似标准来获得,但 _MOTIF_WM_HINTS 属性似乎确实来自... Motif 工具包(好吧,你猜对了 :-))。请参阅MotifZone 网站

警告:以下内容不完整,但我希望能有所启发。

工具包的 XmNmwmDecorations、XmNmwmFunctions 和 XmNmwmInputMode 函数的文档表明该属性是用于控制窗口管理器应提供/赋予的外观、功能(调整大小、移动...)和输入模式的各种值的位掩码窗户。请参阅man vendorshellOreilly Motif 参考书,Vol6a 第 16 章

属性是整个 X11 事物的一部分。一个窗口可以定义任意数量的属性。属性有一个名称,但设置/获取属性是通过“原子”(排序标识符)完成的,以避免在每次 get/set 调用时在线路上发送整个字符串。查看属性和原子

当前的窗口管理器(如果有的话)可以通过设置适当的事件过滤器并作用于 PropertyNotify 事件来对窗口属性更改做出反应,或者只是检查窗口在映射(或移动,或其他)时具有的属性。如果窗口管理器知道 _MOTIF_WM_HINT 属性,它会解释这些并(希望)做你想做的事。(注意:我不确定该权限是否已移交给窗口管理器,或者其他窗口是否可以侦听那些“PropertyNotify”事件。不确定这实际上与您的问题相关。)

因此,只要您的窗口管理器知道 _MOTIF_WM_HINTS 属性,您的代码就可以正常工作。

您首先使用 XInternAtom 为其获取原子(标识符/快捷方式),并在通过 MapWindow() 实际绘制窗口之前通过 XChangeProperty() 设置其值(不确定如果在 MapWindow() 之后执行此操作是否有效,这可能取决于您的窗口管理器)。

[编辑:将 .decorations 部分设置为零会清除所有装饰位,因此这要求窗口管理器让您的边界远离地狱,本质上。]

我无法提出具有该结构定义的“官方”某个地方。它在 openmotif-2.3.3 发行版的 lib/X11/MwmUtils.h 中定义。不确定如何使用 .flags 条目(找不到我一生的代码 :-/ ),但我怀疑它用于指示 {decoration, function, inputMode} “子属性”中的哪个你是作用于。(不要相信我的话。)

附带说明一下,现在使用 _MOTIF_WM_HINTS 可能不是您的最佳选择。您是否查看过 freedesktop上的扩展窗口管理器提示规范和其他信息/标准/草案?我敢打赌,大多数“现代”窗口管理器/桌面环境/厨房水槽都会倾向于坚持这一点,而不是保持与 Motif 的向后兼容性。我猜这一切都取决于你编码的内容。

谢谢阅读 :-)

于 2011-03-03T20:40:54.177 回答
0

看看_MOTIF_WM_HINTS物业。我将您的代码更改为工作状态:

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAPIT
#undef REPEAT

void waitxevt(Display* d, int type)

{

    XEvent e; /* XEvent holder */

    do { XNextEvent(d, &e); } while (e.type != type);

}

void frame(Display* d, Window w, int e)

{

    Atom window_type;
    Atom motif_hints;
    long value;

#ifdef MAPIT
    XUnmapWindow(d, w);
    waitxevt(d, UnmapNotify);
#endif
    window_type = XInternAtom(d, "_NET_WM_WINDOW_TYPE", False);
    if (e) value = XInternAtom(d, "_NET_WM_WINDOW_TYPE_NORMAL", False);
    else value = XInternAtom(d, "_NET_WM_WINDOW_TYPE_DOCK", False);
    XChangeProperty(d, w, window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);
    
    long hints[5] = {e ? 0 : 2, 0, 0, 0, 0};
    motif_hints = XInternAtom(d, "_MOTIF_WM_HINTS", False);

    XChangeProperty(d, w, motif_hints, motif_hints, 32, PropModeReplace, (unsigned char *)&hints, 5);
    
#ifdef MAPIT
    XMapWindow(d, w);
    waitxevt(d, MapNotify);
#endif

}

int main(void) {

    Display*     d;
    Window       w;
    XEvent       e;
    const char*  msg = "Hello, World!";
    int          s;
    GC           gracxt;
    int          frmenb = 0;
 
    d = XOpenDisplay(NULL);
    if (d == NULL) {

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

    }
 
    s = DefaultScreen(d);
    gracxt = XDefaultGC(d, s);

    w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 640, 480, 5,
                            BlackPixel(d, s), WhitePixel(d, s));
    XSelectInput(d, w, ExposureMask|KeyPressMask|StructureNotifyMask);
    XMapWindow(d, w);
    waitxevt(d, MapNotify);

    while (1) {

        XNextEvent(d, &e);
        if (e.type == Expose) XDrawString(d, w, gracxt, 10, 50, msg, strlen(msg));
        if (e.type == KeyPress) {

            frame(d, w, frmenb);
            frmenb = frmenb == 0 ? 1 : 0;
#ifdef REPEAT
            frame(d, w, frmenb);
            frmenb = !frmenb;
#endif

        }

    }

    XCloseDisplay(d);

    return 0;

}

唯一改变的是包括提示。

于 2021-08-18T19:38:36.010 回答