X子结构重定向弄乱工具/菜单栏
下面的代码块启动根窗口下部结构重定向并尝试调整任何新的儿童:X子结构重定向弄乱工具/菜单栏
#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看起来不错,但按下“打开菜单”按钮没有明显效果。改变代码以遵守配置请求可以修复一些问题('打开菜单'按钮仍然不起作用),但是这当然会影响整个目的。我现在想要的只是能够调整窗口大小并重新定位窗口而不会破坏它们。我错过了什么?
[更新]
按照英戈的建议,这里是一个更新的版本不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;
}
没有明显的区别,至于原来的问题有关。
嗯,我不能完全肯定,但有3件事情要考虑:
窗口管理器:通常它的窗口管理器的职责定位和装饰的窗户。你现在试图通过调整窗口大小来颠覆这一点。
复杂的图形用户界面:你正在调整每个窗口的大小,但如果程序创建子窗口?比方说,工具栏是一个子窗口,浏览器面板是一个,另一个是滚动条。你也在调整它们的大小。
意外的行为:所以,我有一个X程序,我创建了一个50x50像素的固定窗口。现在突然有人决定将该窗口设为800x600。我的程序应该做什么?当然,它会很困惑......
您可以到“修复” 2点通过检查窗口是根窗口的直接后代(例如,它是应用程序的顶层窗口),并且只调整这些。
这个程序在我的情况下是窗口管理器。如果我理解正确,一次只有一个客户端可以在根上启动子结构重定向,所以我认为它很清楚。如果工具栏确实是根窗口子窗口的子窗口,则子结构重定向不适用于它(即“WM”不会拦截其配置请求)。最后,虽然我不尊重尺寸提示,但emacs和firefox应该能够处理800x600的尺寸...... – user3026691
1.正如OP所说,这里*是窗口管理器。 2.窗口管理器不关心子窗口,X在应用程序的帮助下处理子窗口。 3.规范非常清晰,应用程序需要处理这些情况。 –
你肯定会做错的一件事是忽略override_redirect。我建议你看看一个简单的窗口管理器的代码,像dwm。 –
我认为override_redirect是X服务器。我会尽快检查。 dwm对于像我这样的初学者来说太神秘了。 – user3026691
dwm非常简单,只需检查它如何处理不同类型的事件。您将收到所有窗口的地图请求,但作为窗口管理器,您不应触摸覆盖重定向窗口。特别是不要调整它们等。 –