XLIB를 사용하여 최상위 X11 Windows를 식별하는 방법은 무엇입니까?
문제
X11 세션에서 모든 최상위 데스크탑 창의 목록을 얻으려고합니다. 기본적으로 Window Managers 애플리케이션 전환 UI에 표시된 모든 Windows의 목록을 얻고 싶습니다 (일반적으로 사용자가 Alt+Tab을 누를 때 열린).
나는 전에 X11 프로그래밍을 한 적이 없지만 지금까지는 전체 창 목록을 통해 다음과 같은 모습을 보이는 코드를 열거했습니다.
void CSoftwareInfoLinux::enumerateWindows(Display *display, Window rootWindow)
{
Window parent;
Window *children;
Window *child;
quint32 nNumChildren;
XTextProperty wmName;
XTextProperty wmCommand;
int status = XGetWMName(display, rootWindow, &wmName);
if (status && wmName.value && wmName.nitems)
{
int i;
char **list;
status = XmbTextPropertyToTextList(display, &wmName, &list, &i);
if (status >= Success && i && *list)
{
qDebug() << "Found window with name:" << (char*) *list;
}
status = XGetCommand(display, rootWindow, &list, &i);
if (status >= Success && i && *list)
{
qDebug() << "... and Command:" << i << (char*) *list;
}
Window tf;
status = XGetTransientForHint(display, rootWindow, &tf);
if (status >= Success && tf)
{
qDebug() << "TF set!";
}
XWMHints *pHints = XGetWMHints(display, rootWindow);
if (pHints)
{
qDebug() << "Flags:" << pHints->flags
<< "Window group:" << pHints->window_group;
}
}
status = XQueryTree(display, rootWindow, &rootWindow, &parent, &children, &nNumChildren);
if (status == 0)
{
// Could not query window tree further, aborting
return;
}
if (nNumChildren == 0)
{
// No more children found. Aborting
return;
}
for (int i = 0; i < nNumChildren; i++)
{
enumerateWindows(display, children[i]);
}
XFree((char*) children);
}
enumerateWindows()
처음에는 루트 창으로 불립니다.
이것은 수백 개의 창문에 대한 정보를 인쇄하는 한 작동합니다. 내가 필요로하는 것은 내가 어떤 속성을 심문 할 수 있는지 알아내는 것입니다. Window
최상위 데스크탑 응용 프로그램 창입니다 (공식 용어가 무엇인지 확실하지 않음).
누구든지 이것에 대해 약간의 빛을 발할 수 있습니까? 내가 찾은 X11 프로그래밍에 대해 찾은 모든 참조 문서는 매우 건조하고 이해하기 어려웠습니다. 아마도 누군가가 더 나은 자원을 가리킬 수 있습니까?
해결책
해결책이 있습니다!
글쎄요, 일종의.
Window Manager가 확장 된 창 관리자 힌트 (EWMH)를 사용하는 경우 "_NET_CLIENT_LIST
"Atom.이 클라이언트 Windows Window Manager 의이 클라이언트 목록. 자세한 내용은 참조하십시오. 여기.
그러나 이것에 몇 가지 문제가 있습니다. 처음에는 사용중인 창 관리자가 EWMH를 지원해야합니다. Kde와 Gnome은 그렇습니다. 나는 다른 사람들도 그렇게 할 것이라고 확신합니다. 그러나 나는 그렇지 않은 많은 것이 있다고 확신합니다. 또한 KDE에 몇 가지 문제가 있음을 알았습니다. 기본적으로 일부 비 KDE 응용 프로그램은 목록에 포함되지 않습니다. 예를 들어, KDE에서 XCALC를 실행하면이 목록에 표시되지 않습니다.
이 방법에 대해 누군가가 개선을 제공 할 수 있다면 기꺼이들을 것입니다. 참고로 사용중인 코드는 다음과 같습니다.
Atom a = XInternAtom(m_pDisplay, "_NET_CLIENT_LIST" , true);
Atom actualType;
int format;
unsigned long numItems, bytesAfter;
unsigned char *data =0;
int status = XGetWindowProperty(m_pDisplay,
rootWindow,
a,
0L,
(~0L),
false,
AnyPropertyType,
&actualType,
&format,
&numItems,
&bytesAfter,
&data);
if (status >= Success && numItems)
{
// success - we have data: Format should always be 32:
Q_ASSERT(format == 32);
// cast to proper format, and iterate through values:
quint32 *array = (quint32*) data;
for (quint32 k = 0; k < numItems; k++)
{
// get window Id:
Window w = (Window) array[k];
qDebug() << "Scanned client window:" << w;
}
XFree(data);
}
다른 팁
이전 솔루션을 확장하려면 창 이름을 얻으려면 다음과 같습니다.
// get window Id:
Window w = (Window) array[k];
char* name = '\0';
status = XFetchName(display, w, &name);
if (status >= Success)
{
if (name == NULL)
printf("Found: %ul NULL\n", w);
else
printf("Found: %ul %s\n", w, name);
}
XFree(name);
xlib를 사용할 필요가없는 경우 GDK를 사용합니다. gdk_screen_get_window_stack()
그리고 gdk_window_get_window_type()
귀하의 요구에 도움이 될 수 있습니다.