Поведение Xlib и Firefox

Я пытаюсь создать небольшой оконный менеджер (просто для удовольствия), но у меня проблемы с обработкой окон, созданных Firefox (только с этим приложением, другие приложения работают нормально)

Проблема в том, что после того, как я запустил Firefox и добавил свое украшение, он, кажется, работает нормально, но если, например, я пытаюсь нажать на кнопку меню, окно (под) не появляется.

Похоже, что после нажатия происходит событие ClientMessage со следующими значениями:

Data: (null)
Data: _NET_WM_STATE_HIDDEN
Data: (null)
Data: (null)
Data: (null)

Теперь проблема в том, что я не знаю, как показать окно, какое окно. Я пробовал с:

XRaiseWindowXMapWindowЯ пытался получить переходное окно и показать его

Но без успеха. Что я не понимаю, так это то, что это клиентское сообщение генерируется подокном меню или нет.

Как мне показать окно в _NET_WM_STATE_HIDDEN?

Другая странная проблема заключается в том, что после получения ClientMessage я всегда получаю 2 события UnMapNotify.

У меня также есть другой вопрос, если я хочу показать меню «Файл, Редактировать» (в Firefox он появляется, если я правильно помню, когда вы нажимаете кнопку Alt.

Может быть, Firefox создает дерево окон?

Это цикл, в котором я обрабатываю события:

while(1){
    XNextEvent(display, &local_event);
    switch(local_event.type){
        case ConfigureNotify:
            configure_notify_handler(local_event, display);
        break;
        case MotionNotify:
            motion_handler(local_event, display);
        break;
        case CreateNotify:
            cur_win = local_event.xcreatewindow.window;
            char *window_name;
            XFetchName(display, cur_win, &window_name);
            printf("Window name: %s\n", window_name);
            if(window_name!=NULL){
                if(!strcmp(window_name, "Parent")){
                    printf("Adding borders\n");
                    XSetWindowBorderWidth(display, cur_win, BORDER_WIDTH);
                }
                XFree(window_name);
            }
        break;
        case MapNotify:
            map_notify_handler(local_event,display, infos);
        break;
        case UnmapNotify: 
            printf("UnMapNotify\n");
        break;
        case DestroyNotify:
            printf("Destroy Event\n");
            destroy_notify_handler(local_event,display);
        break;
        case ButtonPress:
            printf("Event button pressed\n");
            button_handler(local_event, display, infos);
        break;
        case KeyPress:
            printf("Keyboard key pressed\n");
            keyboard_handler(local_event, display);
        break;
        case ClientMessage:
            printf("------------ClientMessage\n");
            printf("\tMessage: %s\n", XGetAtomName(display,local_event.xclient.message_type));
            printf("\tFormat: %d\n", local_event.xclient.format); 
            Atom *atoms = (Atom *)local_event.xclient.data.l;
            int i =0;
            for(i=0; i<=5; i++){
                printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i]));
            }
            int nchild;
            Window *child_windows;
            Window parent_window;
            Window root_window;
            XQueryTree(display, local_event.xclient.window, &root_window, &parent_window, &child_windows, &nchild);
            printf("\tNumber of childs: %d\n", nchild);
        break;
    }

Сейчас в клиентском сообщении на самом деле я просто пытаюсь увидеть, как собирать некоторую информацию, чтобы понять, что происходит. И что я могу видеть из кода выше, это то, что окно, которое вызвало событие, содержит одного дочернего элемента (опять же: это меню? Или нет?)

Код для события MapNotify, куда я добавляю украшение, следующий:

void map_notify_handler(XEvent local_event, Display* display, ScreenInfos infos){
    printf("----------Map Notify\n");
    XWindowAttributes win_attr;
    char *child_name;
    XGetWindowAttributes(display, local_event.xmap.window, &win_attr);
    XFetchName(display, local_event.xmap.window, &child_name);
    printf("\tAttributes: W: %d - H: %d - Name: %s - ID %lu\n", win_attr.width, win_attr.height, child_name, local_event.xmap.window);
    Window trans = None;    
    XGetTransientForHint(display, local_event.xmap.window, &trans); 
    printf("\tIs transient: %ld\n", trans);
    if(child_name!=NULL){
      if(strcmp(child_name, "Parent") && local_event.xmap.override_redirect == False){
        Window new_win = draw_window_with_name(display, RootWindow(display, infos.screen_num), "Parent", infos.screen_num, 
                           win_attr.x, win_attr.y, win_attr.width, win_attr.height+DECORATION_HEIGHT, 0, 
                           BlackPixel(display, infos.screen_num));
        XMapWindow(display, new_win);
        XReparentWindow(display,local_event.xmap.window, new_win,0, DECORATION_HEIGHT);
        set_window_item(local_event.xmap.window, new_win);
        XSelectInput(display, local_event.xmap.window, StructureNotifyMask);
        printf("\tParent window id: %lu\n", new_win);
        put_text(display, new_win, child_name, "9x15", 10, 10, BlackPixel(display,infos.screen_num), WhitePixel(display, infos.screen_num));
      }
    }
    XFree(child_name);
}

Теперь кто-нибудь может мне помочь с этими проблемами? К сожалению, я уже много раз гуглил, но безуспешно.

Подводя итог, у меня две проблемы: 1. Как показать подокна из Firefox 2. Как показать меню Файл, Правка.

ОБНОВИТЬ

Я заметил кое-что странное тестирование Firefox с xev, чтобы понять, какие события запускаются, чтобы показать приложение. Я видел, что при использовании Firefox в единстве и при использовании Firefox в другом менеджере окон события запускаются совершенно по-другому. В Unity у меня есть только:

ClientMessageUnmapNotify

Вместо этого, используя Firefox, например, с xfce4, генерируются xevents:

VisiblityNotify (более одного)Выставить событие (более одного)

Но если я пытаюсь включить VisibilityChangeMask в моем wm, я получаю следующие события:

ConfigureNotifyClientMessageMapNotify2 UnMapNotify

ОБНОВЛЕНИЕ 2

Я попытался прочитать свойства XWMhints в окне ClientMessage (возможно, в окне меню) и значения:

Для флагов 67 = InputHint, StateHint, WIndowGroupHint

Для начального состояния NormalState

ОБНОВЛЕНИЕ 3

Я пытался посмотреть, как работает другой оконный менеджер, и я искал исходный код спокойного. Насколько я понимаю, при получении события ClientMessage с сообщением _NET_WM_STATE они обновляют эти свойства, а в случае _NET_WM_STATE_HIDDEN очищают это свойство, и в результате это свойство будет удалено. Поэтому я попытался обновить свой код, чтобы удалить это свойство, но оно все еще не работает. В любом случае соответствующий обновленный код в client_message_handler теперь выглядит так:

Atom *atoms = (Atom *)local_event.xclient.data.l;
int i =0;
for(i=0; i<=5; i++){
    printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i]));
    if(i==1){
        printf("\t Deleting Property: _NET_WM_STATE_HIDDEN \n");
        XDeleteProperty(display, cur_window, atoms[i]);
    }
}

Это всего лишь тест, и я уверен, что в моем случае i = 1 - это свойство _NET_WM_STATE_HIDDEN.

Вот ссылка на исходный код quietwm:https://github.com/chneukirchen/cwm/blob/linux/xevents.c

Так что я все еще застрял в этой точке.

ОБНОВЛЕНИЕ 4

На самом деле я не знаю, помогает ли это, но я попытался прочитать атрибуты окна в событии MapNotify, и окно map_state имеет вид IsViewable (2).

ОБНОВЛЕНИЕ 5

Я нашел похожую проблему здесь, в SO, используя xlib с python:Xlib Python: не может отобразить меню Firefox

Решение предлагает использовать XSetInputFocus, я попробовал это на моем обработчике XMapNotify:

XSetInputFocus(display, local_event.xmap.window, RevertToParent, CurrentTime);

Но это все равно не помогает, меню Firefox все еще не появляется !! И у меня та же проблема с правой кнопкой мыши.

ОБНОВЛЕНИЕ 6

Играя с событиями xconfigurenotify и unmap, я обнаружил, что запрос: Xconfigure имеет 2 поля окна: window и выше, и когда значение xconfigurerequest.window совпадает со значением xunmap.window.

А также, что xconfigurerequest.above всегда меняется, но xconfigurerequest.window всегда одинаков во всех событиях.

Кажется, что xconfigurerequest.above связан с тем, какое меню я пытаюсь открыть. Например:

если щелкнуть правой кнопкой мыши на странице, я получаю идентификатор (всегда один и тот же для каждого последующего клика)если я щелкну правой кнопкой мыши на вкладке, вышеуказанное значение является еще одними то же самое произойдет, если я щелкну левой кнопкой мыши главное меню Firefox

Все еще не знаю, помогает ли это.

На самом деле не знаю, кто-нибудь есть идеи?

Ответы на вопрос(1)

Ваш ответ на вопрос