我如何捕获 XWindows 中的最小化和最大化事件?
How do I capture minimize and maximize events in XWindows?
我想确定我的 XWindow 是最小化还是最大化。我的示例程序是:
/*
* Study for multiple windows.
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void prtxevtt(int type)
{
switch (type) {
case 2: fprintf(stderr, "KeyPress"); break;
case 3: fprintf(stderr, "KeyRelease"); break;
case 4: fprintf(stderr, "ButtonPress"); break;
case 5: fprintf(stderr, "ButtonRelease"); break;
case 6: fprintf(stderr, "MotionNotify"); break;
case 7: fprintf(stderr, "EnterNotify"); break;
case 8: fprintf(stderr, "LeaveNotify"); break;
case 9: fprintf(stderr, "FocusIn"); break;
case 10: fprintf(stderr, "FocusOut"); break;
case 11: fprintf(stderr, "KeymapNotify"); break;
case 12: fprintf(stderr, "Expose"); break;
case 13: fprintf(stderr, "GraphicsExpose"); break;
case 14: fprintf(stderr, "NoExpose"); break;
case 15: fprintf(stderr, "VisibilityNotify"); break;
case 16: fprintf(stderr, "CreateNotify"); break;
case 17: fprintf(stderr, "DestroyNotify"); break;
case 18: fprintf(stderr, "UnmapNotify"); break;
case 19: fprintf(stderr, "MapNotify"); break;
case 20: fprintf(stderr, "MapRequest"); break;
case 21: fprintf(stderr, "ReparentNotify"); break;
case 22: fprintf(stderr, "ConfigureNotify"); break;
case 23: fprintf(stderr, "ConfigureRequest"); break;
case 24: fprintf(stderr, "GravityNotify"); break;
case 25: fprintf(stderr, "ResizeRequest"); break;
case 26: fprintf(stderr, "CirculateNotify"); break;
case 27: fprintf(stderr, "CirculateRequest"); break;
case 28: fprintf(stderr, "PropertyNotify"); break;
case 29: fprintf(stderr, "SelectionClear"); break;
case 30: fprintf(stderr, "SelectionRequest"); break;
case 31: fprintf(stderr, "SelectionNotify"); break;
case 32: fprintf(stderr, "ColormapNotify"); break;
case 33: fprintf(stderr, "ClientMessage"); break;
case 34: fprintf(stderr, "MappingNotify"); break;
case 35: fprintf(stderr, "GenericEvent"); break;
default: fprintf(stderr, "???"); break;
}
}
int main(void) {
Window w;
GC gracxt;
XEvent e;
const char* msg = "Hello, window";
int s;
XFontStruct* font;
Display* d;
int front = 1;
Atom fullscreen;
int status;
Atom prop;
Atom type;
int format;
unsigned long length;
unsigned long after;
unsigned char* dp;
d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 1000, 1000, 5,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask|KeyPressMask|PointerMotionMask|
StructureNotifyMask|PropertyChangeMask);
XMapWindow(d, w);
gracxt = XCreateGC(d, w, 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, gracxt, font->fid);
fullscreen = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 1);
printf("Fullscreen atom: %ld\n", fullscreen);
while (1) {
XNextEvent(d, &e);
//printf("XWindow event: "); prtxevtt(e.type); printf("\n"); fflush(stdout);
if (e.type == Expose) XDrawString(d, e.xany.window, gracxt, 10, 50, msg, strlen(msg));
else if (e.type == ConfigureNotify) {
printf("ConfigureNotify: x: %d y: %d w: %d h: %d\n",
e.xconfigure.x, e.xconfigure.y, e.xconfigure.width, e.xconfigure.height);
} else if (e.type == PropertyNotify) {
//printf("PropertyNotify: name: %s value: %ld\n", XGetAtomName(d, e.xproperty.atom),
// e.xproperty.atom);
if (!strcmp(XGetAtomName(d, e.xproperty.atom), "_NET_WM_STATE")) {
status = XGetWindowProperty(d, w, e.xproperty.atom,
0L, 1L, 0,
AnyPropertyType, &type, &format,
&length, &after, &dp);
if (status == Success && dp && length) {
prop = ((Atom*)dp)[0];
printf("Property string: %s value: %ld\n", XGetAtomName(d, prop), prop);
}
}
}
XCloseDisplay(d);
return 0;
}
如果我最大化 window 我得到:
ConfigureNotifyXWindow 事件:
配置通知:x:2 y:76 w:4976 h:2752
ExposeXWindow 事件:
这并没有真正告诉我用户最大化了它,只是它变大了。它与屏幕尺寸不匹配,这当然是真的,因为它不包括桌面的标题和菜单栏。
当点击最小化时,程序中根本没有任何指示。
在文档中:“客户端与 Window 管理器通信”
"4.2.5.图标化和去图标化
如果未映射,则 top-level window 将处于 Normal 状态;如果未映射,则处于 Iconic 状态。即使 window 已被重新 parent 也是如此;当切换到 Iconic 状态时,window 管理器将取消映射 window 及其 parent。
客户端可以选择通过 selecting for top-level window 上的 StructureNotify 事件来通知这些状态更改。当它变为 Iconic 时它将接收一个 UnmapNotify 事件,当它变为 Normal 时将接收一个 MapNotify 事件。"
我没有看到所描述的 unmap/mapnotify 行为。应使用 StructureNotifyMask 启用此事件。
工作机器是Ubuntu 20.04 with GDM3.
谢谢,
斯科特·佛朗哥
加利福尼亚州圣何塞
通过 属性Notify 事件我得到:
PropertyNotifyXWindow event:
PropertyNotify: WM_STATE
PropertyNotifyXWindow event:
PropertyNotify: _NET_WM_STATE
PropertyNotifyXWindow event:
PropertyNotify: _GTK_EDGE_CONSTRAINTS
在 minimize/iconify。仍在努力获取原子的数据。
第二次尝试(使用上面的新代码):
PropertyNotifyXWindow event:
PropertyNotify: name: _NET_WM_STATE value: 326
Atom Property Value: a
PropertyNotifyXWindow event:
PropertyNotify: name: _GTK_EDGE_CONSTRAINTS value: 402
Atom Property Value: �
PropertyNotifyXWindow event:
PropertyNotify: name: _NET_WM_STATE value: 326
Atom Property Value: a
我在别处得到了 XGetWindow属性() 示例。我不确定是什么
window 经理想在这里告诉我。数据是另一个原子吗? (一个数字?)。
我从实用程序 xev 中找到了更多信息:
FocusIn event, serial 37, synthetic NO, window 0x4a00001,
mode NotifyNormal, detail NotifyNonlinear
KeymapNotify event, serial 37, synthetic NO, window 0x0,
keys: 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
PropertyNotify event, serial 37, synthetic NO, window 0x4a00001,
atom 0x146 (_NET_WM_STATE), time 4645675, state PropertyNewValue
PropertyNotify event, serial 37, synthetic NO, window 0x4a00001,
atom 0x192 (_GTK_EDGE_CONSTRAINTS), time 4645675, state PropertyNewValue
PropertyNotify event, serial 37, synthetic NO, window 0x4a00001,
atom 0x146 (_NET_WM_STATE), time 4645679, state PropertyNewValue
...
在最大化测试 window 和最小化时给出类似的轨迹。所以它说“state 属性NewValue”,我正在寻找 _NET_WM_STATE_FULLSCREEN。请问我如何找到新的 属性 值是什么?
结语:
我按照提示修改了上面的程序。我注释掉了 non-essential 打印。现在我得到:
属性 字符串:_NET_WM_STATE_MAXIMIZED_HORZ 值:333
配置通知:x:2 y:76 w:4976 h:2752
配置通知:x:20 y:90 w:1000 h:1000
属性 字符串:_NET_WM_STATE_FOCUSED 值:353
属性 字符串:_NET_WM_STATE_HIDDEN 值:330
属性 字符串:_NET_WM_STATE_HIDDEN 值:330
属性 字符串:_NET_WM_STATE_FOCUSED 值:353
最大化 window 时收到 _NET_WM_STATE_MAXIMIZED_HORZ。当 window 被 return 编辑为正常(从最小化或最大化)时,接收到 _NET_WM_STATE_FOCUSED 状态,并且
_NET_WM_STATE_HIDDEN 来自 iconified/minimized.
从互联网上的垃圾箱潜水,我发现:
_NET_WM_STATE_MAXIMIZED_HORZ
或者
_NET_WM_STATE_MAXIMIZED_VERT
均值最大化。
_NET_WM_STATE_HIDDEN
好像是图标化的意思,但是描述“表示如果desktop/viewport处于活动状态并且坐标在屏幕范围内,则window不会在屏幕上可见”,呵呵.
_NET_WM_STATE_FOCUSED
”表示window的装饰画是否处于激活状态
它看起来与“具有键盘焦点”的含义相同。由于您单击 window 到 minimize/maximize window,猜测它可能是此的别名。
无论如何,谢谢大家的帮助,我现在已经有足够的信息了。
斯科特·佛朗哥
加利福尼亚州圣何塞
PS.
观察到的一个小问题是,如果您最大化 window,然后将其最小化(不要 return 正常),然后 select 图标,您会得到
每个事件 _NET_WM_STATE_MAXIMIZED_HORZ,而不是您期望的 _NET_WM_STATE_HIDDEN。不知道这是错误还是什么。
S.
所以我有一个期末学习计划可以完成我想要的事情,所以我将其作为答案发布。之后的评论。
/*
* Study for minimize/maximize/normalize.
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
Window w;
GC gracxt;
XEvent e;
const char* msg = "Hello, window";
int s;
Display* d;
Atom cmaxhorz;
Atom cmaxvert;
Atom cfocused;
Atom chidden;
int maxhorz;
int maxvert;
int focused;
int hidden;
int status;
Atom prop;
Atom type;
int format;
unsigned long length;
unsigned long after;
unsigned char* dp;
int winstate = 0; // 0 = normal, 1 = maximized, 2 = minimized
int lws;
d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 1000, 1000, 5,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask|KeyPressMask|PointerMotionMask|
StructureNotifyMask|PropertyChangeMask);
XMapWindow(d, w);
gracxt = XCreateGC(d, w, 0, NULL);
cfocused = XInternAtom(d, "_NET_WM_STATE_FOCUSED", 1);
cmaxhorz = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_HORZ", 1);
cmaxvert = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_VERT", 1);
chidden = XInternAtom(d, "_NET_WM_STATE_HIDDEN", 1);
while (1) {
XNextEvent(d, &e);
if (e.type == Expose) XDrawString(d, e.xany.window, gracxt, 10, 50, msg, strlen(msg));
else if (e.type == PropertyNotify) {
if (!strcmp(XGetAtomName(d, e.xproperty.atom), "_NET_WM_STATE")) {
after = 1L;
focused = 0;
maxhorz = 0;
maxvert = 0;
hidden = 0;
do {
status = XGetWindowProperty(d, w, e.xproperty.atom,
0L, after, 0,
4/*XA_ATOM*/, &type, &format,
&length, &after, &dp);
if (status == Success && type == 4/*XA_ATOM*/ && dp && format == 32 && length) {
for (int i = 0; i < length; i++) {
prop = ((Atom*)dp)[i];
if (prop == cfocused) focused = 1;
if (prop == cmaxhorz) maxhorz = 1;
if (prop == cmaxvert) maxvert = 1;
if (prop == chidden) hidden = 1;
}
}
} while (after);
if (hidden) {
lws = winstate;
winstate = 2;
if (lws != winstate) printf("Minimized\n");
} else if (maxhorz || maxvert) {
lws = winstate;
winstate = 1;
if (lws != winstate) printf("Maximized\n");
} else if (focused) {
lws = winstate;
winstate = 0;
if (lws != winstate) printf("Normalized\n");
}
}
}
}
XCloseDisplay(d);
return 0;
}
我无法使用 XGetWindowProperty() 找到任何好的程序。那里的所有人都错过了您应该迭代直到“之后”返回 0 的想法。其他人错过了第一次调用也可以包含数据的事实,即使其他调用也是如此。
我仍然对为什么需要多次调用 XGetWindowProperty() 感到困惑。它可以 return 一系列结果,而且似乎没有关于它如何将原子分解成组的押韵或理由。
我不知道是否真的需要获取和存储 _NET_WM_STATE 状态的数字等价物,假设它们在不同的实现中发生变化。我以为他们会。
我使用了 xprop -spy,然后单击 window,查看属性并验证我的程序应该看到什么。
程序将事件塑造成我认为重要的window状态,即最大化(占据整个屏幕)、最小化(一个图标)或正常window。 Xwindows 不这么看,它将水平最大化和垂直最大化分开,一个 window 可以有多个单独的 属性。最小化的 window 也可以最大化,您可以通过以下事实看到这一点:最小化的 window 在被选中时会返回到最大化,而不是标准化。我同意,我认为 window 的三种状态是一个很好的范例。
敏锐的人会意识到 minimize/maximize/normalize 东西来自 MS Windows,这确实是我对代码的原始实现。
我想确定我的 XWindow 是最小化还是最大化。我的示例程序是:
/*
* Study for multiple windows.
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void prtxevtt(int type)
{
switch (type) {
case 2: fprintf(stderr, "KeyPress"); break;
case 3: fprintf(stderr, "KeyRelease"); break;
case 4: fprintf(stderr, "ButtonPress"); break;
case 5: fprintf(stderr, "ButtonRelease"); break;
case 6: fprintf(stderr, "MotionNotify"); break;
case 7: fprintf(stderr, "EnterNotify"); break;
case 8: fprintf(stderr, "LeaveNotify"); break;
case 9: fprintf(stderr, "FocusIn"); break;
case 10: fprintf(stderr, "FocusOut"); break;
case 11: fprintf(stderr, "KeymapNotify"); break;
case 12: fprintf(stderr, "Expose"); break;
case 13: fprintf(stderr, "GraphicsExpose"); break;
case 14: fprintf(stderr, "NoExpose"); break;
case 15: fprintf(stderr, "VisibilityNotify"); break;
case 16: fprintf(stderr, "CreateNotify"); break;
case 17: fprintf(stderr, "DestroyNotify"); break;
case 18: fprintf(stderr, "UnmapNotify"); break;
case 19: fprintf(stderr, "MapNotify"); break;
case 20: fprintf(stderr, "MapRequest"); break;
case 21: fprintf(stderr, "ReparentNotify"); break;
case 22: fprintf(stderr, "ConfigureNotify"); break;
case 23: fprintf(stderr, "ConfigureRequest"); break;
case 24: fprintf(stderr, "GravityNotify"); break;
case 25: fprintf(stderr, "ResizeRequest"); break;
case 26: fprintf(stderr, "CirculateNotify"); break;
case 27: fprintf(stderr, "CirculateRequest"); break;
case 28: fprintf(stderr, "PropertyNotify"); break;
case 29: fprintf(stderr, "SelectionClear"); break;
case 30: fprintf(stderr, "SelectionRequest"); break;
case 31: fprintf(stderr, "SelectionNotify"); break;
case 32: fprintf(stderr, "ColormapNotify"); break;
case 33: fprintf(stderr, "ClientMessage"); break;
case 34: fprintf(stderr, "MappingNotify"); break;
case 35: fprintf(stderr, "GenericEvent"); break;
default: fprintf(stderr, "???"); break;
}
}
int main(void) {
Window w;
GC gracxt;
XEvent e;
const char* msg = "Hello, window";
int s;
XFontStruct* font;
Display* d;
int front = 1;
Atom fullscreen;
int status;
Atom prop;
Atom type;
int format;
unsigned long length;
unsigned long after;
unsigned char* dp;
d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 1000, 1000, 5,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask|KeyPressMask|PointerMotionMask|
StructureNotifyMask|PropertyChangeMask);
XMapWindow(d, w);
gracxt = XCreateGC(d, w, 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, gracxt, font->fid);
fullscreen = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 1);
printf("Fullscreen atom: %ld\n", fullscreen);
while (1) {
XNextEvent(d, &e);
//printf("XWindow event: "); prtxevtt(e.type); printf("\n"); fflush(stdout);
if (e.type == Expose) XDrawString(d, e.xany.window, gracxt, 10, 50, msg, strlen(msg));
else if (e.type == ConfigureNotify) {
printf("ConfigureNotify: x: %d y: %d w: %d h: %d\n",
e.xconfigure.x, e.xconfigure.y, e.xconfigure.width, e.xconfigure.height);
} else if (e.type == PropertyNotify) {
//printf("PropertyNotify: name: %s value: %ld\n", XGetAtomName(d, e.xproperty.atom),
// e.xproperty.atom);
if (!strcmp(XGetAtomName(d, e.xproperty.atom), "_NET_WM_STATE")) {
status = XGetWindowProperty(d, w, e.xproperty.atom,
0L, 1L, 0,
AnyPropertyType, &type, &format,
&length, &after, &dp);
if (status == Success && dp && length) {
prop = ((Atom*)dp)[0];
printf("Property string: %s value: %ld\n", XGetAtomName(d, prop), prop);
}
}
}
XCloseDisplay(d);
return 0;
}
如果我最大化 window 我得到:
ConfigureNotifyXWindow 事件: 配置通知:x:2 y:76 w:4976 h:2752 ExposeXWindow 事件:
这并没有真正告诉我用户最大化了它,只是它变大了。它与屏幕尺寸不匹配,这当然是真的,因为它不包括桌面的标题和菜单栏。
当点击最小化时,程序中根本没有任何指示。
在文档中:“客户端与 Window 管理器通信”
"4.2.5.图标化和去图标化 如果未映射,则 top-level window 将处于 Normal 状态;如果未映射,则处于 Iconic 状态。即使 window 已被重新 parent 也是如此;当切换到 Iconic 状态时,window 管理器将取消映射 window 及其 parent。 客户端可以选择通过 selecting for top-level window 上的 StructureNotify 事件来通知这些状态更改。当它变为 Iconic 时它将接收一个 UnmapNotify 事件,当它变为 Normal 时将接收一个 MapNotify 事件。"
我没有看到所描述的 unmap/mapnotify 行为。应使用 StructureNotifyMask 启用此事件。
工作机器是Ubuntu 20.04 with GDM3.
谢谢,
斯科特·佛朗哥 加利福尼亚州圣何塞
通过 属性Notify 事件我得到:
PropertyNotifyXWindow event:
PropertyNotify: WM_STATE
PropertyNotifyXWindow event:
PropertyNotify: _NET_WM_STATE
PropertyNotifyXWindow event:
PropertyNotify: _GTK_EDGE_CONSTRAINTS
在 minimize/iconify。仍在努力获取原子的数据。
第二次尝试(使用上面的新代码):
PropertyNotifyXWindow event:
PropertyNotify: name: _NET_WM_STATE value: 326
Atom Property Value: a
PropertyNotifyXWindow event:
PropertyNotify: name: _GTK_EDGE_CONSTRAINTS value: 402
Atom Property Value: �
PropertyNotifyXWindow event:
PropertyNotify: name: _NET_WM_STATE value: 326
Atom Property Value: a
我在别处得到了 XGetWindow属性() 示例。我不确定是什么 window 经理想在这里告诉我。数据是另一个原子吗? (一个数字?)。
我从实用程序 xev 中找到了更多信息:
FocusIn event, serial 37, synthetic NO, window 0x4a00001,
mode NotifyNormal, detail NotifyNonlinear
KeymapNotify event, serial 37, synthetic NO, window 0x0,
keys: 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
PropertyNotify event, serial 37, synthetic NO, window 0x4a00001,
atom 0x146 (_NET_WM_STATE), time 4645675, state PropertyNewValue
PropertyNotify event, serial 37, synthetic NO, window 0x4a00001,
atom 0x192 (_GTK_EDGE_CONSTRAINTS), time 4645675, state PropertyNewValue
PropertyNotify event, serial 37, synthetic NO, window 0x4a00001,
atom 0x146 (_NET_WM_STATE), time 4645679, state PropertyNewValue
...
在最大化测试 window 和最小化时给出类似的轨迹。所以它说“state 属性NewValue”,我正在寻找 _NET_WM_STATE_FULLSCREEN。请问我如何找到新的 属性 值是什么?
结语:
我按照提示修改了上面的程序。我注释掉了 non-essential 打印。现在我得到:
属性 字符串:_NET_WM_STATE_MAXIMIZED_HORZ 值:333 配置通知:x:2 y:76 w:4976 h:2752 配置通知:x:20 y:90 w:1000 h:1000 属性 字符串:_NET_WM_STATE_FOCUSED 值:353 属性 字符串:_NET_WM_STATE_HIDDEN 值:330 属性 字符串:_NET_WM_STATE_HIDDEN 值:330 属性 字符串:_NET_WM_STATE_FOCUSED 值:353
最大化 window 时收到 _NET_WM_STATE_MAXIMIZED_HORZ。当 window 被 return 编辑为正常(从最小化或最大化)时,接收到 _NET_WM_STATE_FOCUSED 状态,并且 _NET_WM_STATE_HIDDEN 来自 iconified/minimized.
从互联网上的垃圾箱潜水,我发现:
_NET_WM_STATE_MAXIMIZED_HORZ 或者 _NET_WM_STATE_MAXIMIZED_VERT
均值最大化。
_NET_WM_STATE_HIDDEN
好像是图标化的意思,但是描述“表示如果desktop/viewport处于活动状态并且坐标在屏幕范围内,则window不会在屏幕上可见”,呵呵.
_NET_WM_STATE_FOCUSED
”表示window的装饰画是否处于激活状态
它看起来与“具有键盘焦点”的含义相同。由于您单击 window 到 minimize/maximize window,猜测它可能是此的别名。
无论如何,谢谢大家的帮助,我现在已经有足够的信息了。
斯科特·佛朗哥 加利福尼亚州圣何塞
PS.
观察到的一个小问题是,如果您最大化 window,然后将其最小化(不要 return 正常),然后 select 图标,您会得到 每个事件 _NET_WM_STATE_MAXIMIZED_HORZ,而不是您期望的 _NET_WM_STATE_HIDDEN。不知道这是错误还是什么。
S.
所以我有一个期末学习计划可以完成我想要的事情,所以我将其作为答案发布。之后的评论。
/*
* Study for minimize/maximize/normalize.
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
Window w;
GC gracxt;
XEvent e;
const char* msg = "Hello, window";
int s;
Display* d;
Atom cmaxhorz;
Atom cmaxvert;
Atom cfocused;
Atom chidden;
int maxhorz;
int maxvert;
int focused;
int hidden;
int status;
Atom prop;
Atom type;
int format;
unsigned long length;
unsigned long after;
unsigned char* dp;
int winstate = 0; // 0 = normal, 1 = maximized, 2 = minimized
int lws;
d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 1000, 1000, 5,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask|KeyPressMask|PointerMotionMask|
StructureNotifyMask|PropertyChangeMask);
XMapWindow(d, w);
gracxt = XCreateGC(d, w, 0, NULL);
cfocused = XInternAtom(d, "_NET_WM_STATE_FOCUSED", 1);
cmaxhorz = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_HORZ", 1);
cmaxvert = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_VERT", 1);
chidden = XInternAtom(d, "_NET_WM_STATE_HIDDEN", 1);
while (1) {
XNextEvent(d, &e);
if (e.type == Expose) XDrawString(d, e.xany.window, gracxt, 10, 50, msg, strlen(msg));
else if (e.type == PropertyNotify) {
if (!strcmp(XGetAtomName(d, e.xproperty.atom), "_NET_WM_STATE")) {
after = 1L;
focused = 0;
maxhorz = 0;
maxvert = 0;
hidden = 0;
do {
status = XGetWindowProperty(d, w, e.xproperty.atom,
0L, after, 0,
4/*XA_ATOM*/, &type, &format,
&length, &after, &dp);
if (status == Success && type == 4/*XA_ATOM*/ && dp && format == 32 && length) {
for (int i = 0; i < length; i++) {
prop = ((Atom*)dp)[i];
if (prop == cfocused) focused = 1;
if (prop == cmaxhorz) maxhorz = 1;
if (prop == cmaxvert) maxvert = 1;
if (prop == chidden) hidden = 1;
}
}
} while (after);
if (hidden) {
lws = winstate;
winstate = 2;
if (lws != winstate) printf("Minimized\n");
} else if (maxhorz || maxvert) {
lws = winstate;
winstate = 1;
if (lws != winstate) printf("Maximized\n");
} else if (focused) {
lws = winstate;
winstate = 0;
if (lws != winstate) printf("Normalized\n");
}
}
}
}
XCloseDisplay(d);
return 0;
}
我无法使用 XGetWindowProperty() 找到任何好的程序。那里的所有人都错过了您应该迭代直到“之后”返回 0 的想法。其他人错过了第一次调用也可以包含数据的事实,即使其他调用也是如此。
我仍然对为什么需要多次调用 XGetWindowProperty() 感到困惑。它可以 return 一系列结果,而且似乎没有关于它如何将原子分解成组的押韵或理由。
我不知道是否真的需要获取和存储 _NET_WM_STATE 状态的数字等价物,假设它们在不同的实现中发生变化。我以为他们会。
我使用了 xprop -spy,然后单击 window,查看属性并验证我的程序应该看到什么。
程序将事件塑造成我认为重要的window状态,即最大化(占据整个屏幕)、最小化(一个图标)或正常window。 Xwindows 不这么看,它将水平最大化和垂直最大化分开,一个 window 可以有多个单独的 属性。最小化的 window 也可以最大化,您可以通过以下事实看到这一点:最小化的 window 在被选中时会返回到最大化,而不是标准化。我同意,我认为 window 的三种状态是一个很好的范例。
敏锐的人会意识到 minimize/maximize/normalize 东西来自 MS Windows,这确实是我对代码的原始实现。