以下代码在根窗口上启动子结构重定向并尝试调整任何新子窗口的大小:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#define TERMINAL "urxvt"
void start(char* what)
{
if(!fork())
{
char* const args[] = {"/bin/sh", "-c", what, NULL};
execvp("/bin/sh", args);
exit(1);
}
}
int main()
{
Display* dpy;
Window root;
XSetWindowAttributes setAttribs;
XEvent ev;
if(!(dpy = XOpenDisplay(NULL)))
exit(1);
root = XDefaultRootWindow(dpy);
XSelectInput(dpy, root, SubstructureNotifyMask | SubstructureRedirectMask);
XGrabKey(dpy, XKeysymToKeycode(dpy, XK_T), Mod4Mask, root, True, GrabModeAsync, GrabModeAsync);
while(1)
{
XNextEvent(dpy, &ev);
switch(ev.type)
{
case MapRequest:
XMapWindow(dpy, ev.xmaprequest.window);
XMoveResizeWindow(dpy, ev.xmaprequest.window, 0, 0, 800, 600);
XSync(dpy, False);
break;
case KeyPress:
start(TERMINAL);
break;
default:
break;
}
}
XUngrabKey(dpy, AnyKey, AnyModifier, root);
XSync(dpy, False);
return 0;
}
这似乎适用于简单的终端(您可以使用 Mod4+t 启动由 TERMINAL 常量定义的终端),但会混淆更复杂的 GUI 中的各个部分。例如,emacs 显示时没有工具栏,并且菜单栏在必要时不会自行重绘。Firefox 看起来不错,但按下“打开菜单”按钮没有明显效果。更改代码以尊重配置请求修复了一些问题(“打开菜单”按钮仍然不起作用),但这当然会破坏整个目的。在这一点上,我想要的只是能够在不破坏窗口的情况下调整大小和重新定位窗口。我错过了什么?
[更新]
根据 Ingo 的建议,这是一个更新版本,它不会触及设置了 override_redirect 的窗口:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#define TERMINAL "urxvt"
void start(char* what)
{
if(!fork())
{
char* const args[] = {"/bin/sh", "-c", what, NULL};
execvp("/bin/sh", args);
exit(1);
}
}
int hasOverrideRedirect(Display* dpy, Window win)
{
XWindowAttributes wa;
if(!XGetWindowAttributes(dpy, win, &wa))
return 0;
return wa.override_redirect;
}
int main()
{
Display* dpy;
Window root;
XSetWindowAttributes setAttribs;
XEvent ev;
if(!(dpy = XOpenDisplay(NULL)))
exit(1);
root = XDefaultRootWindow(dpy);
XSelectInput(dpy, root, SubstructureNotifyMask | SubstructureRedirectMask);
XGrabKey(dpy, XKeysymToKeycode(dpy, XK_T), Mod4Mask, root, True, GrabModeAsync, GrabModeAsync);
while(1)
{
XNextEvent(dpy, &ev);
switch(ev.type)
{
case MapRequest:
XMapWindow(dpy, ev.xmaprequest.window);
if(!hasOverrideRedirect(dpy, ev.xmaprequest.window))
{
XMoveResizeWindow(dpy, ev.xmaprequest.window, 0, 0, 800, 600);
XSync(dpy, False);
}
break;
case KeyPress:
start(TERMINAL);
break;
case ConfigureRequest:
if(hasOverrideRedirect(dpy, ev.xconfigurerequest.window))
{
XConfigureRequestEvent *e2 = &ev.xconfigurerequest;
XWindowChanges wc;
wc.x = e2->x;
wc.y = e2->y;
wc.width = e2->width;
wc.height = e2->height;
wc.border_width = e2->border_width;
wc.sibling = e2->above;
wc.stack_mode = e2->detail;
XConfigureWindow(dpy, e2->window, e2->value_mask, &wc);
}
default:
break;
}
}
XUngrabKey(dpy, AnyKey, AnyModifier, root);
XSync(dpy, False);
return 0;
}
就原始问题而言,没有明显的区别。