使用下面的代码,我在X11上激活一个窗口。
我正在使用FindWindow获取窗口句柄,这很好用。 然后我想把指定的窗口放在前台。 为此,我使用XRaiseWindow。
XRaiseWindow(display, wdThisWindow);
然而,XRaiseWindow在某些窗口上不起作用(很多,但不是全部)。 我想这是因为他们的override_redirect WindowAttribute没有设置为true。 所以我使用XChangeWindowAttributes将此属性设置为true。 现在,XRaiseWindow将所有窗口都带到了顶部。 问题是,EyeOfGnome(图片浏览器)和所有其他应用程序都丢失了顶部的标题栏...(你知道,右边有一个关闭控件的那个......)。 更糟糕的是,窗户不再出现在背景中......
我想如果我在提升窗口后设置了override_redirect属性,问题就会消失。 但... 问题现在已经从所有应用程序(例如gnome-terminal)消失 - 除了EyeOfGnome(图片查看器)......
我错过了什么,或者这是一个EyeOfGnome问题,还是一般的GTK问题?
以下是导致问题的部分代码:
XSetWindowAttributes xswa;
xswa.override_redirect = True;
XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
XRaiseWindow(display, wdThisWindow);
xswa.override_redirect = False;
XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
XSetInputFocus(display, wdThisWindow, RevertToNone, CurrentTime);
这是完整的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
// Info: xwininfo
// I am compiling using
// gcc -o activate activate.c -L/usr/X11R6/lib -lX11
// ERROR HANDLER, GENERIC
static int ErrorHandler (Display *display, XErrorEvent *error)
{
//printf ("\r\n error! \r\n");// gcc -o xwinspy lol.c -L/usr/X11R6/lib -lX11
return 0;
}
// END ERROR HANDLER
// Recursively search through all windows on display
Window SearchWindow(char* szWindowToFind, int level, Display *display, Window rootWindow, int iMatchMode, int showErrors)
{
Window parent;
Window *children;
unsigned int noOfChildren;
int status;
int i;
Window wSearchedWindow = 0;
char* win_name;
if (XFetchName(display, rootWindow, &win_name))
{
//printf("WinName (Level %d): %s\n", level, win_name);
if(iMatchMode == 0)
{
if( strstr(win_name, szWindowToFind) )
{
return rootWindow;
}
}
else if(iMatchMode == 1)
{
if( !strcmp(win_name, szWindowToFind) )
{
return rootWindow;
}
}
else if(iMatchMode == 2)
{
if( strcasestr(win_name, szWindowToFind) )
{
return rootWindow;
}
}
else if(iMatchMode == 3)
{
if( !strcasecmp(win_name, szWindowToFind) )
{
return rootWindow;
}
}
else
{
if( strstr(win_name, szWindowToFind) )
{
return rootWindow;
}
}
} // End if XFetchName
status = XQueryTree (display, rootWindow, &rootWindow, &parent, &children, &noOfChildren);
if (status == 0)
{
if (showErrors)
printf ("ERROR - Could not query the window tree. Aborting.\r\n");
return;
}
if (noOfChildren > 0)
{
for (i=0; i < noOfChildren; i++)
{
wSearchedWindow = SearchWindow(szWindowToFind, level+1, display, children[i], iMatchMode, showErrors);
if(wSearchedWindow)
{
break;
}
}
}
XFree ((char*) children);
return wSearchedWindow;
} // End Sub EnumerateWindows
Window FindWindow(char* szWindowToFind)
{
Display *display = XOpenDisplay (NULL);
int screen = DefaultScreen (display);
XSetErrorHandler(ErrorHandler);
Window rootWindow = RootWindow (display, screen);
Window wSearchedWindow = SearchWindow(szWindowToFind, 0, display, rootWindow, 0, 0);
char* win_name;
if (XFetchName(display, wSearchedWindow, &win_name))
{
printf("Found: %s\n", win_name);
}
XCloseDisplay (display);
return wSearchedWindow;
}
void ActivateWindow(char* szWindow)
{
Window wdThisWindow = FindWindow(szWindow);
Display *display = XOpenDisplay (NULL);
char* win_name;
if (XFetchName(display, wdThisWindow, &win_name))
{
printf("Activating: %s\n", win_name);
}
XSetErrorHandler(ErrorHandler);
XSetWindowAttributes xswa;
xswa.override_redirect = True;
XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
XRaiseWindow(display, wdThisWindow);
xswa.override_redirect = False;
XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
XSetInputFocus(display, wdThisWindow, RevertToNone, CurrentTime);
XCloseDisplay (display);
}
// ENUMARATE THROUGH WINDOWS AND DISPLAY THEIR TITLES
void EnumerateWindows(int level, Display *display, Window rootWindow, int showErrors)
{
Window parent;
Window *children;
unsigned int noOfChildren;
int status;
int i;
char* win_name;
if (XFetchName(display, rootWindow, &win_name))
{
printf("Window-Name (Level %d): %s\n", level, win_name);
}
status = XQueryTree (display, rootWindow, &rootWindow, &parent, &children, &noOfChildren);
if (status == 0)
{
if (showErrors)
printf ("ERROR - Could not query the window tree. Aborting.\r\n");
return;
}
if (noOfChildren > 0)
{
for (i=0; i < noOfChildren; i++)
{
EnumerateWindows(level+1, display, children[i], showErrors);
}
}
XFree ((char*) children);
} // End Sub EnumerateWindows
void ListAllWindowsOnScreen()
{
Display *display = XOpenDisplay (NULL);
int screen = DefaultScreen (display);
XSetErrorHandler(ErrorHandler);
Window rootWindow = RootWindow (display, screen);
EnumerateWindows(0, display, rootWindow, 0);
XCloseDisplay (display);
}
int main(int argc, char *argv[])
{
ListAllWindowsOnScreen();
//ActivateWindow("000727");
return EXIT_SUCCESS;
}
答案 0 :(得分:6)
正如ninjalj所提到的,你要做的就是使用EWMH规范中的协议,而不是制作这些原始的X协议请求。你在这里做的事情会让GTK +和窗口管理器混淆不清。
具体来说,你想要做的是发送_NET_ACTIVE_WINDOW客户端消息,用 来源指示(http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#sourceindication)可能会说你是一个寻呼机。
顺便提一下,有一个名为libwnck的库(我最初编写但其他人现在维护)将为您完成所有这些操作。即使你不使用它,你也可以查看它的源代码来学习如何做事。
答案 1 :(得分:4)