c - 如何正确设置 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 之间移植的工具包的一部分。框架开/关用于两个目的(到目前为止):
- 制作没有框架的组件窗口(小部件)。
- 切换框架。例如,我有一个时钟程序,如果你点击它,它会移除框架,使它变得更小和不动。再次单击将其恢复。
第一个现在可以工作,因为它只关闭一次框架,并且发生在映射之前。第二个不起作用。
新程序,现在可以使用,使用以下建议:
/*
* 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;
}
解决方案
推荐阅读
- javascript - 错误 [ERR_MODULE_NOT_FOUND]:找不到模块
- javascript - 为什么 CSS 和浏览器根本不重新加载更改?
- java - 由于找不到 aws 区域,单元测试失败并出现 IllegalArgumentException
- react-native - 将大的 fetch 请求分解为较小的请求
- grafana - 如何使用 grafana 和 influxdb 显示传感器状态?
- c++ - 如何在 C++ 中注册一个动态成员
- service - 读取 WFS 服务数据
- ios - iOS 14 requestTrackingAuthorization 状态总是被拒绝
- flutter - 为什么 Dart 中的类型检查如此奇怪?
- python - 为什么easy_install在jython2.7中输出错误?