0

以下代码在根窗口上启动子结构重定向并尝试调整任何新子窗口的大小:

#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;
}

就原始问题而言,没有明显的区别。

4

1 回答 1

-1

好吧,我不完全确定,但有 3 件事需要考虑:

  • 窗口管理器:通常由窗口管理器负责定位和装饰窗口。您现在正试图通过动态调整窗口大小来颠覆这一点。

  • 复杂的 GUI:您正在调整每个窗口的大小,但如果程序创建子窗口怎么办?比如说,工具栏是一个子窗口,浏览器面板是一个,滚动条是另一个。您也在调整它们的大小。

  • 意外行为:所以,我有一个 X 程序并创建了一个 50x50 像素的固定窗口。现在突然有人决定将该窗口设置为 800x600。我的程序应该做什么?肯定会糊涂...

您可以通过检查窗口是否是根窗口的直接后代(例如,它是应用程序的顶级窗口)来“修复”第 2 点,并且只调整它们的大小。

于 2016-02-01T13:46:20.287 回答