首页 > 解决方案 > 如何正确设置 xwindows 属性

问题描述

给定代码:

/*
 * XWindows study on if we can turn the frame on and off.
 */
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAPIT
#define 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;
    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);
#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;
#ifdef REPEAT
            frame(d, w, frmenb);
            frmenb = !frmenb;
#endif

        }

    }

    XCloseDisplay(d);

    return 0;

}

代码的目的是打开和关闭窗口 w 的框架。在没有映射/取消映射操作的情况下,“关闭”调用正常工作,并且窗口更改(在屏幕上)没有框架,并且不那么大,并且不再出现标题栏。

但是,在使用例程重新打开它时,标题栏不可见,但它是相当大的。如果调整窗口大小,标题栏会重新出现。

建议在设置属性之前取消映射窗口并在之后重新映射。这样做的结果是,没有框架的窗口不再能够获得焦点,从而无法获得变回的键。我设置了一个“重复”标志,使其立即恢复到全帧模式,从而证明恢复取景有效。确实如此。另一个副作用是地图操作后窗口的位置被重置,但我可以弥补这一点。

这是在 Ubuntu 20.04 上。

什么目的?此代码是在 Windows 和 Linux 之间移植的工具包的一部分。框架开/关用于两个目的(到目前为止):

  1. 制作没有框架的组件窗口(小部件)。
  2. 切换框架。例如,我有一个时钟程序,如果你点击它,它会移除框架,使它变得更小和不动。再次单击将其恢复。

第一个现在可以工作,因为它只关闭一次框架,并且发生在映射之前。第二个不起作用。

新程序,现在可以使用,使用以下建议:

/*
 * XWindows study on if we can turn the frame on and off.
 */
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct MwmHints {
    unsigned long flags;
    unsigned long functions;
    unsigned long decorations;
    long input_mode;
    unsigned long status;
};
enum {
    MWM_HINTS_FUNCTIONS = (1L << 0),
    MWM_HINTS_DECORATIONS =  (1L << 1),

    MWM_FUNC_ALL = (1L << 0),
    MWM_FUNC_RESIZE = (1L << 1),
    MWM_FUNC_MOVE = (1L << 2),
    MWM_FUNC_MINIMIZE = (1L << 3),
    MWM_FUNC_MAXIMIZE = (1L << 4),
    MWM_FUNC_CLOSE = (1L << 5)
};

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

{

    Atom mwmHintsProperty;
    struct MwmHints hints;

    mwmHintsProperty = XInternAtom(d, "_MOTIF_WM_HINTS", 0);
    hints.flags = MWM_HINTS_DECORATIONS;
    hints.decorations = !!e;
    XChangeProperty(d, w, mwmHintsProperty, mwmHintsProperty, 32,
                        PropModeReplace, (unsigned char *)&hints, 5);

}

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);

    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;

        }

    }

    XCloseDisplay(d);

    return 0;

}

标签: cx11

解决方案


推荐阅读