2016-02-01 9 views
0

Следующий фрагмент кода инициирует подструктуру перенаправлением на корневом окне и пытается изменить размер новых детей:X Несущая Перенаправление Messes Up Tool/Menu Bars

#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), но запутывает различные части в более сложных графических интерфейсах. Например, emacs появляется без панели инструментов, и панель меню при необходимости не перерисовывает. Firefox отлично выглядит, но нажатие кнопки «open menu» не имеет видимого эффекта. Изменение кода для соблюдения конфигурационных запросов устраняет некоторые проблемы (кнопка «открыть меню» все еще не работает), но это, конечно же, побеждает всю цель. Все, что я хочу в этот момент, - это возможность изменять размер и изменять положение окон, не нарушая их. Что мне не хватает?

[UPDATE]

По предложению Инго, вот обновленная версия, которая не задевает окна с 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; 
} 

Нет заметную разницы, насколько исходная проблема затронута.

+0

Одна вещь, которую вы точно делаете неправильно, игнорирует override_redirect. Я бы посоветовал вам взглянуть на простой код оконного менеджера, что-то вроде dwm. –

+0

Я думал, что override_redirect был для X-сервера. Я проверю это, как только смогу. dwm слишком загадочно для новичка, подобного мне. – user3026691

+0

dwm довольно просто, просто проверьте, как он обрабатывает различные типы событий. Вы получите запросы на карту для всех окон, но в качестве диспетчера окон вы не должны прикасаться к переопределению окон переадресации. В частности, не изменяйте их размер и т. Д. –

ответ

-1

Ну, я не совсем уверен, но есть 3 вещи, которые необходимо учитывать:

  • Window Manager: как правило, это ответственность менеджера окон для размещения и украсить окна. Вы пытаетесь подорвать это, изменив размер окна на лету.

  • Сложные графические интерфейсы: вы изменяете размер каждого окна, но что делать, если программы создают подокна? Скажем, панель инструментов - это одна подзаголовок, панель браузера - одна, а вторая - полоса прокрутки. Вы также изменяете их размеры.

  • Неожиданное поведение: так, у меня есть программа X, и я создаю фиксированное окно размером 50x50 пикселей. Теперь вдруг кто-то решает сделать это окно 800x600. Что должна моя программа? Конечно, это запутывается ...

Вы можете быть в состоянии «исправить» точку 2, проверяя, если окно является прямым потомком корневого окна (например, это окно верхнего уровня приложения), и только измените их размер.

+0

Эта программа _is_ оконный менеджер в моем случае. Если я правильно понимаю, только один клиент за раз может инициировать перенаправление подструктуры на корне, поэтому я подумал, что это понятно. Если панель инструментов действительно является дочерней частью дочернего элемента корневого окна, то перенаправление подструктуры не относится к ней (т. Е. «WM» не будет перехватывать свои запросы конфигурации). Наконец, хотя это правда, что я не отношусь к советам по размеру, emacs и firefox должны иметь возможность обрабатывать размер 800x600 ... – user3026691

+0

1. Как сказал OP, это * - это оконный менеджер здесь. 2. Диспетчер окон не заботится о subwindows, X позаботится об этом с помощью приложения. 3. В спецификации очень четко говорится о том, что приложениям необходимо иметь дело с этими ситуациями. –