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

これは、単純な端末 ( TERMINAL 定数で定義されたものを Mod4+t で起動できます) では問題なく動作するように見えますが、より複雑な 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: すべてのウィンドウのサイズを変更していますが、プログラムがサブウィンドウを作成するとどうなるでしょうか? たとえば、ツールバーは 1 つのサブウィンドウ、ブラウザー パネルは 1 つ、スクロールバーは別のサブウィンドウです。それらのサイズも変更しています。

  • 予期しない動作: X プログラムがあり、50x50 ピクセルの固定ウィンドウを作成します。ここで突然、誰かがそのウィンドウを 800x600 にすることにしました。私のプログラマーは何をすべきですか?? 確かに混む…。

ウィンドウがルート ウィンドウの直接の子孫であるかどうか (たとえば、アプリケーションのトップ レベル ウィンドウであるかどうか) をチェックすることでポイント 2 を「修正」し、それらのサイズのみを変更できる場合があります。

于 2016-02-01T13:46:20.287 に答える