#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/Xmu/WinUtil.h>
char *ProgramName;
static void lookat ( Display *dpy, Window root, Bool verbose, int maxcmdlen );
static void print_client_properties ( Display *dpy, Window w,
Bool verbose, int maxcmdlen );
static void print_text_field ( Display *dpy, char *s, XTextProperty *tp );
static int print_quoted_word ( char *s, int maxlen );
static void unknown ( Display *dpy, Atom actual_type, int actual_format );
static void
usage(void)
{
fprintf (stderr,
"usage: %s [-display dpy] [-m len] [-[a][l]]\n", ProgramName);
exit (1);
}
int
main(int argc, char *argv[])
{
int i;
char *displayname = NULL;
Bool all_screens = False;
Bool verbose = False;
Display *dpy;
int maxcmdlen = 10000;
ProgramName = argv[0];
for (i = 1; i < argc; i++) {
char *arg = argv[i];
if (arg[0] == '-') {
char *cp;
switch (arg[1]) {
case 'd':
if (++i >= argc) usage ();
displayname = argv[i];
continue;
case 'm':
if (++i >= argc) usage ();
maxcmdlen = atoi (argv[i]);
continue;
}
for (cp = &arg[1]; *cp; cp++) {
switch (*cp) {
case 'a':
all_screens = True;
continue;
case 'l':
verbose = True;
continue;
default:
usage ();
}
}
} else {
usage ();
}
}
dpy = XOpenDisplay (displayname);
if (!dpy) {
fprintf (stderr, "%s: unable to open display \"%s\"\r\n",
ProgramName, XDisplayName (displayname));
exit (1);
}
if (all_screens) {
for (i = 0; i < ScreenCount(dpy); i++) {
lookat (dpy, RootWindow(dpy,i), verbose, maxcmdlen);
}
} else {
lookat (dpy, DefaultRootWindow(dpy), verbose, maxcmdlen);
}
XCloseDisplay (dpy);
exit (0);
}
static void
lookat(Display *dpy, Window root, Bool verbose, int maxcmdlen)
{
Window dummy, *children = NULL, client;
unsigned int i, nchildren = 0;
print_client_properties (dpy, root, verbose, maxcmdlen);
if (!XQueryTree (dpy, root, &dummy, &dummy, &children, &nchildren)) {
return;
}
for (i = 0; i < nchildren; i++) {
client = XmuClientWindow (dpy, children[i]);
if (client != None)
print_client_properties (dpy, client, verbose, maxcmdlen);
}
}
static char *Nil = "(nil)";
static void
print_client_properties(Display *dpy, Window w, Bool verbose, int maxcmdlen)
{
char **cliargv = NULL;
int i, cliargc;
XTextProperty nametp, machtp, tp;
int charsleft = maxcmdlen;
if (!XGetWMClientMachine (dpy, w, &machtp)) {
machtp.value = NULL;
machtp.encoding = None;
}
if (!XGetCommand (dpy, w, &cliargv, &cliargc)) {
if (machtp.value) XFree ((char *) machtp.value);
return;
}
if (verbose) {
printf ("Window 0x%lx:\n", w);
print_text_field (dpy, " Machine: ", &machtp);
if (XGetWMName (dpy, w, &nametp)) {
print_text_field (dpy, " Name: ", &nametp);
if (nametp.value) XFree ((char *) nametp.value);
}
} else {
print_text_field (dpy, NULL, &machtp);
putchar (' ');
putchar (' ');
}
if (machtp.value) XFree ((char *) machtp.value);
if (verbose) {
if (XGetWMIconName (dpy, w, &tp)) {
print_text_field (dpy, " Icon Name: ", &tp);
if (tp.value) XFree ((char *) tp.value);
}
}
if (verbose) {
printf (" Command: ");
}
for (i = 0; i < cliargc && charsleft > 0; ) {
charsleft -= print_quoted_word (cliargv[i], charsleft);
i++;
if (i < cliargc && charsleft > 0) {
putchar (' '); charsleft--;
}
}
putchar ('\n');
XFreeStringList (cliargv);
if (verbose) {
XClassHint clh;
if (XGetClassHint (dpy, w, &clh)) {
printf (" Instance/Class: %s/%s",
clh.res_name ? clh.res_name : Nil,
clh.res_class ? clh.res_class : Nil);
if (clh.res_name) XFree (clh.res_name);
if (clh.res_class) XFree (clh.res_class);
putchar ('\n');
}
}
}
static void
print_text_field(Display *dpy, char *s, XTextProperty *tp)
{
if (tp->encoding == None || tp->format == 0) {
printf ("''");
return;
}
if (s) printf ("%s", s);
if (tp->encoding == XA_STRING && tp->format == 8) {
printf ("%s", tp->value ? (char *) tp->value : Nil);
} else {
unknown (dpy, tp->encoding, tp->format);
}
if (s) putchar ('\n');
}
static int
print_quoted_word(char *s,
int maxlen)
{
register char *cp;
Bool need_quote = False, in_quote = False;
char quote_char = '\'', other_quote = '"';
int charsprinted = 0;
for (cp = s; *cp; cp++) {
if (! ((isascii(*cp) && isalnum(*cp)) ||
(*cp == '-' || *cp == '_' || *cp == '.' || *cp == '+' ||
*cp == '/' || *cp == '=' || *cp == ':' || *cp == ','))) {
need_quote = True;
break;
}
}
in_quote = need_quote;
if (need_quote) {
putchar (quote_char);
charsprinted++; maxlen--;
}
for (cp = s; *cp && maxlen>0; cp++) {
if (*cp == quote_char) {
if (in_quote) {
putchar (quote_char);
charsprinted++; maxlen--;
}
putchar (other_quote);
charsprinted++; maxlen--;
{
char tmp = other_quote;
other_quote = quote_char; quote_char = tmp;
}
in_quote = True;
}
putchar (*cp);
charsprinted++; maxlen--;
}
if (in_quote && maxlen>0) {
putchar (quote_char);
charsprinted++; maxlen--;
}
return charsprinted;
}
static void
unknown(Display *dpy, Atom actual_type, int actual_format)
{
char *s;
printf ("<unknown type ");
if (actual_type == None) printf ("None");
else if ((s = XGetAtomName (dpy, actual_type)) != NULL) {
fputs (s, stdout);
XFree (s);
} else {
fputs (Nil, stdout);
}
printf (" (%ld) or format %d>", actual_type, actual_format);
}