使用下面的代码,我在 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;
}
最佳答案
正如 ninjalj 提到的,您必须做的是使用 EWMH 规范中的协议(protocol),而不是发出这些原始 X 协议(protocol)请求。您在这里所做的事情会混淆 GTK+ 和窗口管理器。
具体来说,您在这里要做的是发送一条 _NET_ACTIVE_WINDOW 客户端消息,其中包含 来源指示 (http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#sourceindication) 可能设置为说您是寻呼机。
顺便说一句,有一个名为 libwnck 的库(我最初编写但现在其他人维护)可以为您完成所有这些工作。即使您不使用它,您也可以查看其源代码以了解如何使用它。
关于c - 在 X11 上激活一个窗口,为什么我会丢失标题栏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5367806/