的Xlib和Firefox的行为 [英] Xlib and Firefox behavior

查看:179
本文介绍了的Xlib和Firefox的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个小的窗口管理器(只是为了好玩),但我有在处理由火狐(只与应用,其他应用程序正常工作)创建的窗口的问题。

问题是,我启动Firefox后,并加入我的装饰,看起来做工精细,但如果比如我尝试点击菜单键,(子)窗口不会出现。

有什么事发生的是,点击后,一个ClientMessage事件与以下值触发:

 数据:(空)
数据:_NET_WM_STATE_HIDDEN
数据:(空)
数据:(空)
数据:(空)

现在的问题是,我不知道如何来显示窗口,哪个窗口。
我试着用:


  • XRaiseWindow

  • XMapWindow

  • 我试图让短暂的窗口,并显示它

但没有成功。我不明白的是,如果通过菜单子窗口或不产生此客户端消息。

我应该如何显示一个窗口,在_NET_WM_STATE_HIDDEN?

另一个奇怪的问题是,接受ClientMessage后,我总是收到2 UnMapNotify活动。

我也有另外一个问题,如果我想显示文件,编辑菜单(在Firefox看来,如果我没有记错,当你preSS Alt键的。

也许火狐创建窗口的树?

这是我处理事件循环:

 而(1){
    XNextEvent例行(显示器,功放及; local_event);
    开关(local_event.type){
        案例ConfigureNotify:
            configure_notify_handler(local_event,显示器);
        打破;
        案例MotionNotify:
            motion_handler(local_event,显示器);
        打破;
        案例CreateNotify:
            cur_win = local_event.xcreatewindow.window;
            字符* window_name;
            XFetchName(显示,cur_win,&安培; window_name);
            的printf(窗口名称:%s \\ n,window_name);
            如果(window_name!= NULL){
                如果(!STRCMP(window_name,父)){
                    的printf(添加边框的\\ n);
                    XSetWindowBorderWidth(显示,cur_win,BORDER_WIDTH);
                }
                XFree的(window_name);
            }
        打破;
        案例MapNotify:
            map_notify_handler(local_event,显示相关信息);
        打破;
        案例UnmapNotify:
            的printf(UnMapNotify \\ n);
        打破;
        案例DestroyNotify:
            的printf(Destroy事件\\ n);
            destroy_notify_handler(local_event,显示器);
        打破;
        案例按钮preSS:
            的printf(事件按钮pressed \\ n);
            button_handler(local_event,显示相关信息);
        打破;
        案例重点preSS:
            的printf(键盘键pressed \\ n);
            keyboard_handler(local_event,显示器);
        打破;
        案例ClientMessage:
            的printf(------------ ClientMessage \\ n);
            的printf(\\ tMessage:%S \\ n,XGetAtomName(显示器,local_event.xclient.message_type));
            的printf(\\ tFormat数:%d \\ n,l​​ocal_event.xclient.format);
            原子的原子* =(原子*)local_event.xclient.data.l;
            INT I = 0;
            对于(i = 0; I< = 5;我++){
                的printf(\\ t \\ TDATA%D:%S \\ n,我,XGetAtomName(显示,原子由[i]));
            }
            INT nchild;
            窗口* child_windows;
            窗口parent_window;
            窗口root_window;
            XQueryTree(显示,local_event.xclient.window,&安培; root_window,&安培; parent_window,&安培; child_windows,&安培; nchild);
            的printf(童车的\\ tNumber数:%d \\ n,nchild);
        打破;
    }

现在在clientmessage其实我只是想看看收集一些信息,了解发生了什么。而我可以从上面的code看到的,是引发事件的窗口包含一个孩子(也是:是菜单或不?)

在code为MapNotify活动期间,凡我添加了装修如下:

 无效map_notify_handler(XEvent local_event,显示*显示,ScreenInfos的相关信息){
    的printf(----------地图通知\\ n);
    XWindowAttributes win_attr;
    字符* CHILD_NAME;
    XGetWindowAttributes(显示,local_event.xmap.window,&安培; win_attr);
    XFetchName(显示,local_event.xmap.window,&安培; CHILD_NAME);
    的printf(\\ tAttributes:W:%d个 - H:%d个 - 名称:%s - ID%禄\\ n,win_attr.width,win_attr.height,CHILD_NAME,local_event.xmap.window);
    窗反=无;
    XGetTransientForHint(显示,local_event.xmap.window,&安培;反式);
    的printf(\\ t已瞬态:%ld个\\ N,反式);
    如果(CHILD_NAME!= NULL){
      如果(STRCMP(CHILD_NAME,父)及和放大器; local_event.xmap.override_redirect ==假){
        窗口new_win = draw_window_with_name(显示器,RootWindow(显示器,infos.screen_num),父母,infos.screen_num,
                           win_attr.x,win_attr.y,win_attr.width,win_attr.height + DECORATION_HEIGHT,0,
                           BlackPixel(显示器,infos.screen_num));
        XMapWindow(显示器,new_win);
        XReparentWindow(显示,local_event.xmap.window,new_win,0,DECORATION_HEIGHT);
        set_window_item(local_event.xmap.window,new_win);
        XSelectInput(显示,local_event.xmap.window,StructureNotifyMask);
        的printf(\\ tParent窗口ID:%lu个\\ N,new_win);
        put_text(显示,new_win,CHILD_NAME,9x15,10,10,BlackPixel(显示,infos.screen_num),WhitePixel(显示,infos.screen_num));
      }
    }
    XFree的(CHILD_NAME);
}

现在有人可以帮助我的这些问题呢?不幸的是,我已经用Google搜索了很多次,但都没有成功。

要总结起来,我的问题有两个:
1.如何显示从Firefox子窗口
2.如何显示文件,编辑菜单。

更新

我发现了一些奇怪的测试火狐xev的明白了什么事件,以显示一个应用程序被解雇。我看到,在统一使用Firefox,而在另一个窗口管理器使用的是Firefox,触发的事件是完全不同的。在Unity我只有:


  1. ClientMessage

  2. UnmapNotify

代替使用火狐

,例如用XFCE4,产生的xevents更


  1. VisiblityNotify(不止一个)

  2. 揭露事件(不止一个)

但是,如果我尝试启用VisibilityChangeMask在我的WM,我收到以下事件:


  • ConfigureNotify

  • ClientMessage

  • MapNotify

  • 2 UnMapNotify

更新2

我试图读取ClientMessage窗口XWMhints属性(大概菜单窗口)和值是:


  • 有关标志67 = InputHint,StateHint,WIndowGroupHint


  • 有关初始状态NormalState


更新3

我想看看另一个窗口管理器是如何工作的,我一直在寻找calmwm源$ C ​​$ C。这是我的理解是,当ClientMessage事件到达,具有_NET_WM_STATE消息时,它更新这些性能,并在_NET_WM_STATE_HIDDEN的情况下,它清除该属性,其结果将是,该属性将被删除。于是,我就更新我的code删除该财产,但它仍然没有工作。反正在client_message_handler相关更新code现在看起来是这样的:

 的Atom *原子=(凌动*)local_event.xclient.data.l;
INT I = 0;
对于(i = 0; I< = 5;我++){
    的printf(\\ t \\ TDATA%D:%S \\ n,我,XGetAtomName(显示,原子由[i]));
    如果(ⅰ== 1){
        的printf(\\ t删除属性:_NET_WM_STATE_HIDDEN \\ n);
        XDeleteProperty(显示,cur_window,原子由[i]);
    }
}

这只是一个测试,我敢肯定,我= 1在我的情况是_NET_WM_STATE_HIDDEN财产。

下面的链接calmwm源$ C ​​$ C:<一href=\"https://github.com/chneukirchen/cwm/blob/linux/xevents.c\">https://github.com/chneukirchen/cwm/blob/linux/xevents.c

所以,我仍然停留在这一点上。

更新4

真的,我不知道是否有帮助,但我试图读取MapNotify事件的属性窗口,窗口map_state是IsViewable(2)。

更新5

我发现了一个类似的问题在这里SO就是使用Xlib与Python: Xlib的蟒蛇:无法映射Firefox的菜单

解决方案建议使用XSetInputFocus,我想这对我的XMapNotify处理程序:

  XSetInputFocus(显示器,local_event.xmap.window,RevertToParent,CURRENTTIME);

但它仍然没有帮助,Firefox菜单仍然没有出现!
和我有右键同样的问题。

更新6

与xconfigurenotify事件和取消映射事件打我发现:
Xconfigure要求有2个窗口字段:窗口及以上,且当
该xconfigurerequest.window值相同xunmap.window价值。

和也认为xconfigurerequest.above总是在变,但xconfigurerequest.window总是在所有的事件一样。

看来,xconfigurerequest.above是关系到我想要开什么菜单。例如:


  • 页面我得到一个ID(总是相同的,以后每点击)。如果右键单击

  • 如果一个标签上我右clik,上述值是另外一个

  • 和相同的发生,如果我离开,点击Firefox的主菜单

不过不知道是否有帮助。

真的不知道
任何人有什么想法?


解决方案

使用的 xtruss - 一个易于使用的X协议跟踪程序


  

  
  

概述


  
  

习惯于在Linux或System V型的Unix将遇到了各种被称为strace的或桁架方案,它监视另一个程序,并生成每个系统的详细日志调用程序,使编写程序的任何程序员 - 换句话说,所有操作系统内核程序的交互。这通常是一个非常宝贵的调试工具,几乎一样好一个教育。


  
  

当它是一个GUI程序(或更确切地说,一个程序的图形用户界面相关的行为)要理解或调试,虽然,与OS内核相互作用的水平很少是最有益的。更有益,人们想记录在以同样的方式在X服务器的所有程序的交互。


  
  

程序已经存在,将做到这一点。我知道XMON和X跟踪的。但他们往往需要大量的努力来建立:你要运行的程序建立一个监听的服务器,然后手动安排目标程序联系的,而不是真正的服务器 - 包括XAUTH一些繁琐的工作。理想情况下,你想跟踪程序公司的X操作是一样究其内核系统调用一样简单:你要输入的strace的程序名论点一样简单的命令,并拥有一切为你自动处理
  
  

此外,这些程序的输出是不容易阅读比我已经喜欢 - 由我基本上意味着它不像strace的比我想的那样。 strace的具有把每个系统调用,并在同一行输出它的返回值,这样就可以一目了然看到每一个反应是响应​​的很好的特性。 X协议监视器,然而,往往遵循X协议的结构忠实,这意味着每个请求和响应被印刷有序列号,并且必须由眼睛到两个匹配


  
  

所以这个页面presents xtruss,我自己X协议记录器领域的贡献。它有类似strace的命令行语法 - 在默认模式下,你只需preFIXxtruss给你无论如何都会运行相同的命令行 - 和它的输出格式也更喜欢strace的,把请求和响应在同一行输出在合理可行的。


  
  

strace的还支持连接到一个已经运行的进程,并从它的运转过程中跟踪它的功能 - 方便出问题的时候有一个长期运行的进程,你不事先知道你会要追踪。 xtruss支持此相同的特征,由X RECORD扩展部分(前提是您的X服务器支持它,这现代X.Org的人做);因此,在这种模式下,您可以识别一个窗口,用鼠标(如xwininfo和xkill标准程序类似),并xtruss将附加到拥有您指定的窗口中的X客户端程序,并开始跟踪它。


  
  

  
  

说明


  
  

xtruss是记录X服务器以及一个或多个X客户端程序之间传递的一切工具。在此它是类似于XMON(1),但为了XMON的基本功能与接口更类似于与strace结合(1)。


  
  

像XMON,xtruss在默认模式下设置代理X服务器,等待该连接​​,并在转发他们是真正的X服务器工作。然而,与XMON,你不必应付用手任何认为:没有必要启动一个终端跟踪工具和手动从另一个附加进程,除非你真的想(在这种情况下 - -P选项将这样做)。使用的主要方式就是键入xtruss其次是你的X程序的命令行; xtruss将自动完成调整新方案的环境在其代理服务器来指向,以及(也不像XMON),它也会自动照顾X授权的。


  
  

由于使用的另一种方式,还可以附加xtruss到一个已经运行的X应用程序,如果你不知道你打算要跟踪它,直到它已经开始了。这种模式需要从X服务器的合作 - 特别是,它不能正常工作,除非服务器支持记录协议扩展 - 但因为现代X.Org服务器都提供了,但是这是


I'm trying to create a small window manager (just for fun), but I'm having problems in handling windows created by Firefox (only with that application, other apps works fine)

The problem is, after I launch Firefox, and add my decoration, it seems to work fine, but if for example I try to click on the menu button, the (sub)window doesn't appear.

What seems to happen is that after the click, a ClientMessage event is fired with the following values:

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

Now the problem is that I don't know how to show the window, which window. I tried with:

  • XRaiseWindow
  • XMapWindow
  • I tried to get the transient window and show it

But without success. What I don't understand is that if this client message is generated by the menu subwindow or not.

How should I show a window that is in _NET_WM_STATE_HIDDEN?

Another strange problem is that after receiving the ClientMessage, I always receive 2 UnMapNotify Events.

I also have another question, if I want to show the "File, Edit" menù (in Firefox it appears, if I remember correctly, when you press the Alt button.

Maybe Firefox creates a tree of windows?

This is the loop where I handle the events:

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

Now in the clientmessage actually I'm just trying to see collect some information to understand what is happening. And what I can see from the code above, is that the window that raised the event contains one child (again: is that the menu? or not?)

The code for the MapNotify event, where I add the decoration is the following:

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

Now can someone help me with these problems? Unfortunately I already googled many times, but without success.

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.

这篇关于的Xlib和Firefox的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆