programing

Xlib 및 Firefox 동작

nasanasas 2020. 12. 2. 21:27
반응형

Xlib 및 Firefox 동작


작은 창 관리자 (재미 용)를 만들려고하는데 Firefox에서 만든 창을 처리하는 데 문제가 있습니다 (해당 응용 프로그램에서만 다른 앱이 잘 작동 함).

문제는 Firefox를 시작하고 장식을 추가 한 후 제대로 작동하는 것 같지만 예를 들어 메뉴 버튼을 클릭하려고하면 (하위) 창이 나타나지 않습니다.

클릭 후 다음 값으로 ClientMessage 이벤트가 발생하는 것으로 보입니다.

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

이제 문제는 창을 표시하는 방법을 모르겠다는 것입니다. 나는 시도했다 :

  • XRaiseWindow
  • XMapWindow
  • 일시적인 창을 가져 와서 보여 주려고했습니다.

그러나 성공하지 못했습니다. 내가 이해하지 못하는 것은이 클라이언트 메시지가 메뉴 하위 창에 의해 생성되는지 여부입니다.

_NET_WM_STATE_HIDDEN에있는 창을 어떻게 표시해야합니까?

또 다른 이상한 문제는 ClientMessage를 수신 한 후 항상 2 개의 UnMapNotify 이벤트를 수신한다는 것입니다.

"파일, 편집"메뉴를 표시하려면 또 다른 질문이 있습니다 (Firefox에서는 Alt 버튼을 눌렀을 때 올바르게 기억하면 나타납니다.

파이어 폭스가 창 트리를 생성할까요?

이것은 내가 이벤트를 처리하는 루프입니다.

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

이제 clientmessage에서 실제로 나는 무슨 일이 일어나고 있는지 이해하기 위해 정보를 수집하는 것을 보려고합니다. 그리고 위의 코드에서 볼 수있는 것은 이벤트를 발생시킨 창에 자식 하나가 포함되어 있다는 것입니다 (다시 말하지만 메뉴입니까?).

장식을 추가하는 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);
}

이제 누군가가 이러한 문제로 나를 도울 수 있습니까? 불행히도 나는 이미 여러 번 봤지만 성공하지 못했습니다.

To sum up, my issues are two: 1. How to show subwindows from Firefox 2. How to show the File, Edit menu.

UPDATE

I noticed something strange testing Firefox with xev to understand what events are fired in order to show an application. I saw that using Firefox in unity, and using Firefox in another window manger, the events fired are completely different. In Unity I have only:

  1. ClientMessage
  2. UnmapNotify

Instead using Firefox, for example with xfce4, the xevents generated are more:

  1. VisiblityNotify (more than one)
  2. Expose event (more than one)

But if I try to enable VisibilityChangeMask in my wm, I receive the following events:

  • ConfigureNotify
  • ClientMessage
  • MapNotify
  • 2 UnMapNotify

UPDATE 2

I tried to read the XWMhints properties in the ClientMessage window (probably the menù window) and the values are:

  • For the flags 67 = InputHint, StateHint, WIndowGroupHint

  • For the initial state NormalState

UPDATE 3

I tried to look how another window manager works, and I was looking at the source code of calmwm. What is my understanding is that, when the ClientMessage event arrives, with a _NET_WM_STATE message, it updates these properties, and in the case of _NET_WM_STATE_HIDDEN it clears this property, and the result will be that the property will be deleted. So I tried to update my code to delete that property, but it's still not working. Anyway the relevant updated code in client_message_handler now looks like this:

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

It is only a test, and I'm sure that i=1 in my case is the _NET_WM_STATE_HIDDEN property.

Here a link to calmwm source code: https://github.com/chneukirchen/cwm/blob/linux/xevents.c

So I'm still stuck at that point.

UPDATE 4

Really I don't know if it helps, but I tried to read the window attributes in the MapNotify Event, and the window map_state is IsViewable (2).

UPDATE 5

I found a similar problem here in SO, using xlib with python: Xlib python: cannot map firefox menus

The solution suggests to use XSetInputFocus, i tried that on my XMapNotify handler:

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

But it still doesn't help, the firefox menu still doesn't appear!! And i have the same problem with right-click.

UPDATE 6

Playing with xconfigurenotify event and unmap event i found that the: Xconfigure request has 2 window fields: window and above, and when the the xconfigurerequest.window value is the same of xunmap.window value.

And also that the xconfigurerequest.above is always changing, but xconfigurerequest.window is always the same in all events.

It seems that the xconfigurerequest.above is related to what menu i'm trying to open. For example:

  • if right-click on a page i get an id (always the same for every subsequent click)
  • if i right-clik on a tab, the above value is another one
  • and the same happen if i left-click the firefox main menu

Still don't know if that helps.

Really don't know Anyone got any idea?


Use xtrussan easy-to-use X protocol tracing program


Overview

Any programmer accustomed to writing programs on Linux or System V-type Unixes will have encountered the program variously known as strace or truss, which monitors another program and produces a detailed log of every system call the program makes – in other words, all the program's interactions with the OS kernel. This is often an invaluable debugging tool, and almost as good an educational one.

When it's a GUI program (or rather, the GUI-related behaviour of a program) that you want to understand or debug, though, the level of interaction with the OS kernel is rarely the most useful one. More helpfully, one would like to log all the program's interactions with the X server in the same way.

Programs already exist that will do this. I'm aware of Xmon and Xtrace. But they tend to require a lot of effort to set up: you have to run the program to establish a listening server, then manually arrange for the target program to contact that instead of the real server – including some fiddly work with xauth. Ideally, you'd like tracing a program's X operations to be just as easy as tracing its kernel system calls: you'd like to type a command as simple as strace program-name arguments, and have everything automatically handled for you.

Also, the output of those programs is less easy to read than I'd have liked – by which I largely mean it's less like strace than I'd like it to be. strace has the nice property of putting each system call and its return value on the same line of output, so that you can see at a glance what each response was a response to. X protocol monitors, however, tend to follow the structure of the X protocol faithfully, meaning that each request and response is printed with a sequence number, and you have to match the two up by eye.

So this page presents xtruss, my own contribution to the field of X protocol loggers. It has a command-line syntax similar to strace – in its default mode, you just prefix "xtruss" to the same command line you would have run anyway – and its output format is also more like strace, putting requests and responses on the same line of output where reasonably possible.

strace also supports the feature of attaching to an already-running process and tracing it from the middle of its run – handy when something goes wrong with a long-running process that you didn't know in advance you were going to need to trace. xtruss supports this same feature, by means of the X RECORD extension (provided your X server supports it, which modern X.Org ones do); so in that mode, you can identify a window with the mouse (similarly to standard programs like xwininfo and xkill), and xtruss will attach to the X client program that owns the window you specified, and begin tracing it.


Description

xtruss is a utility which logs everything that passes between the X server and one or more X client programs. In this it is similar to xmon(1), but intended to combine xmon's basic functionality with an interface much more similar to strace(1).

Like xmon, xtruss in its default mode works by setting up a proxy X server, waiting for connections to that, and forwarding them on to the real X server. However, unlike xmon, you don't have to deal with any of that by hand: there's no need to start the trace utility in one terminal and manually attach processes to it from another, unless you really want to (in which case the -P option will do that). The principal mode of use is just to type xtruss followed by the command line of your X program; xtruss will automatically take care of adjusting the new program's environment to point at its proxy server, and (also unlike xmon) it will also take care of X authorisation automatically.

As an alternative mode of use, you can also attach xtruss to an already-running X application, if you didn't realise you were going to want to trace it until it had already been started. This mode requires cooperation from the X server – specifically, it can't work unless the server supports the RECORD protocol extension – but since modern X.Org servers do provide that, it's often useful.

참고URL : https://stackoverflow.com/questions/31535560/xlib-and-firefox-behavior

반응형