我正在try 创建一个小窗口管理器(只是为了好玩),但在处理Firefox创建的窗口时遇到了问题(只有使用该应用程序,其他应用程序才能正常工作)
问题是,在我启动Firefox并添加我的装饰之后,它似乎工作得很好,但例如,如果我试图单击菜单按钮,(子)窗口就不会出现.
似乎发生的情况是,在单击之后,将使用以下值激发客户信息事件:
Data: (null)
Data: _NET_WM_STATE_HIDDEN
Data: (null)
Data: (null)
Data: (null)
现在的问题是,我不知道如何显示窗口,哪个窗口.
- XRaiseWindow
- XMapWindow
- 我试图获取临时窗口并将其显示出来
但没有成功.我不明白的是,这个客户端消息是否由菜单子窗口生成.
我应该如何显示处于网络状态的窗口?
另一个奇怪的问题是,在收到客户信息后,我总是收到两个未通知的事件.
我还有另一个问题,如果我想显示"File,Edit"menù(在Firefox中,如果我没记错的话,当你按下Alt按钮时,它会出现).
也许Firefox会创建一个windows树?
这是我处理事件的循环:
while(1){
XNextEvent(display, &local_event);
switch(local_event.type){
case 配置通知:
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 map 通知:
map_notify_handler(local_event,display, infos);
break;
case 取消映射通知:
printf("Un map 通知\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 客户信息:
printf("------------客户信息\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中,实际上我只是想看看,收集一些信息来了解发生了什么.从上面的代码中我可以看到,引发事件的窗口包含一个子窗口(同样:这是菜单吗?还是不是?)
我添加装饰的 map 通知事件的代码如下:
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);
}
有人能帮我解决这些问题吗?不幸的是,我已经在谷歌上搜索了很多次,但都没有成功.
总而言之,我的问题有两个:
UPDATE个
我注意到在使用xev测试Firefox时出现了一些奇怪的情况,以了解为了显示应用程序而触发了哪些事件.我看到在unity中使用Firefox,在另一个窗口管理器中使用Firefox,触发的事件完全不同.在团结中,我只有:
- 客户信息
- 取消映射通知
相反,使用Firefox,例如xfce4,生成的xevents更多:
- VisiblityNotify(多个)
- expose 事件(多个)
但如果我try 在wm中启用VisibilityChangeMask,我会收到以下事件:
- 配置通知
- 客户信息
- map 通知
- 2 Un map 通知
UPDATE 2个
我试图在客户信息窗口(可能是menù窗口)中读取XWMhints属性,其值如下:
对于标志67=InputHint、StateHint、WIndowGroupHint
对于初始状态NormalState
UPDATE 3个
我试着看看另一个窗口管理器是如何工作的,我在看calmwm的源代码.我的理解是,当客户信息事件到达时,带有_NET_WM_STATE消息,它会更新这些属性,在_NET_WM_STATE_HIDDEN的情况下,它会清除该属性,结果是该属性将被删除.所以我试图更新我的代码来删除那个属性,但它仍然不起作用.无论如何,客户端消息处理程序中的相关更新代码现在如下所示:
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_HIDDED属性.
这里有指向calmwm源代码的链接:https://github.com/chneukirchen/cwm/blob/linux/xevents.c
所以我仍然停留在这一点上.
UPDATE 4
我真的不知道这是否有帮助,但我try 在 map 通知事件中读取窗口属性,窗口映射_状态是可见的(2).
UPDATE 5
我在SO中发现了类似的问题,使用xlib和python:Xlib python: cannot map firefox menus
解决方案建议使用XSetInputFocus,我在我的X map 通知处理程序上进行了try :
XSetInputFocus(display, local_event.xmap.window, RevertToParent, CurrentTime);
但它仍然没有帮助,firefox菜单仍然没有出现!!
UPDATE 6
在使用xconfigurenotify事件和unmap事件时,我发现:
此外,上面的xconfiguration erequest.window总是在变化,但是在所有事件中xconfiguration erequest.window始终是相同的.
上面的xconfiguration erequest.似乎与我试图打开的菜单有关.例如:
- 如果右键单击某个页面,我会得到一个ID(每次后续单击总是相同的)
- 如果我在选项卡上单击鼠标右键,则上面的值是另一个值
- 如果我左键单击Firefox主菜单,也会发生同样的情况
还是不知道这是否有帮助.
真的不知道 有谁知道吗?