Под Linux / X- Windows Я пытался получить рекурсивный список windows. Моя конечная цель - составить список windows с идентификатором, положением, размерами и названием. Некоторые windows (например, xeyes
) не имеют заголовка окна в окне верхнего уровня. Необходимо найти первое дочернее окно, чтобы оно могло быть читаемым человеком.
Так что я закончил писать код для рекурсивной выборки каждого окна. Однако список окон, возвращаемый XQueryTree()
, похоже, содержит поврежденные данные - некоторые дочерние идентификаторы окон равны нулю. Таким образом, похоже, что XQueryTree()
возвращает неправильное количество дочерних элементов (которое должно соответствовать длине выделенного параметра children_list
).
В конечном итоге код , в основном , завершается с BadWindow
ошибка. Выполнение его через valgrind
показывает конец чтения данных, выделенных XQueryTree()
.
// COMPILE: gcc -Wall -g recursive_window_count.c -o recursive_window_count -lX11
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#define MAX_INDENT 100
unsigned int getWindowCount( Display *display, Window parent_window, int depth )
{
Window root_return;
Window parent_return;
Window *children_list = NULL;
unsigned int list_length = 0;
char indent[MAX_INDENT+1];
// Make some indentation space, depending on the depth
memset( indent, '\0', MAX_INDENT+1 );
for ( int i=0; i<depth*4 && i<MAX_INDENT; i++ )
{
indent[i] = ' ';
}
// query the window list recursively, until each window reports no sub-windows
printf( "getWindowCount() - %sWindow %lu\n", indent, parent_window );
if ( 0 != XQueryTree( display, parent_window, &root_return, &parent_return, &children_list, &list_length ) )
{
printf( "getWindowCount() - %s %d window handle returned\n", indent, list_length );
if ( list_length > 0 && children_list != NULL )
{
for ( int i=0; i<list_length; i++)
{
// But typically the "top-level" window is not what the user sees, so query any children
// Only the odd window has child-windows. XEyes does.
if ( children_list[i] != 0 )
{
unsigned int child_length = getWindowCount( display, children_list[i], depth+1 );
list_length += child_length;
}
else
{
// There's some weirdness with the returned list
// We should not have to be doing this at all
printf( "%sHuh? child window handle at index #%d (of %d) is zero?\n", indent, i, list_length );
break;
}
}
XFree( children_list ); // cleanup
}
}
return list_length;
}
int main( int argc, char **argv )
{
Display *display;
Window root_window;
display = XOpenDisplay( NULL );
if ( display )
{
// Get the number of screens, it's not always one!
int screen_count = XScreenCount( display );
// Each screen has a root window
printf( "There are %d screens available on this X Display\n", screen_count );
for ( int i=0; i < screen_count; i++ )
{
root_window = XRootWindow( display, i );
printf( "Screen %d - %u windows\n", i, getWindowCount( display, root_window, 0 ) );
}
XCloseDisplay( display );
}
return 0;
}
Заголовок valgrind
журнала:
prompt> valgrind ./recursive_window_count
==5117== Memcheck, a memory error detector
==5117== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5117== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==5117== Command: ./recursive_window_count
==5117==
There are 1 screen available on this X Display
getWindowCount() - Window 625
getWindowCount() - 105 window handles returned
getWindowCount() - Window 48234747
getWindowCount() - 1 window handle returned
getWindowCount() - Window 75497478
getWindowCount() - 1 window handle returned
getWindowCount() - Window 75497479
getWindowCount() - 0 window handles returned
==5117== Invalid read of size 8
==5117== at 0x1093CD: getWindowCount (recursive_window_count.c:38)
==5117== by 0x109406: getWindowCount (recursive_window_count.c:40)
==5117== by 0x109530: main (recursive_window_count.c:77)
==5117== Address 0x4bff508 is 0 bytes after a block of size 8 alloc'd
==5117== at 0x483A723: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==5117== by 0x483D017: realloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==5117== by 0x489A53B: XQueryTree (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==5117== by 0x10934D: getWindowCount (recursive_window_count.c:29)
==5117== by 0x109406: getWindowCount (recursive_window_count.c:40)
==5117== by 0x109530: main (recursive_window_count.c:77)
==5117==
Huh? child window handle at index #1 (of 2) is zero?
getWindowCount() - Window 48236534
getWindowCount() - 1 window handle returned
getWindowCount() - Window 96468999
getWindowCount() - 1 window handle returned
getWindowCount() - Window 96469000
getWindowCount() - 0 window handles returned
Huh? child window handle at index #1 (of 2) is zero?
... truncated