xwininfo.c revision ff7e0acc
1ff7e0accSmrg/* $XdotOrg: $ */
2ff7e0accSmrg/* $Xorg: xwininfo.c,v 1.4 2001/02/09 02:06:04 xorgcvs Exp $ */
3ff7e0accSmrg/*
4ff7e0accSmrg
5ff7e0accSmrgCopyright 1987, 1998  The Open Group
6ff7e0accSmrgCopyright 1999 Sun Microsystems, Inc.
7ff7e0accSmrg
8ff7e0accSmrgPermission to use, copy, modify, distribute, and sell this software and its
9ff7e0accSmrgdocumentation for any purpose is hereby granted without fee, provided that
10ff7e0accSmrgthe above copyright notice appear in all copies and that both that
11ff7e0accSmrgcopyright notice and this permission notice appear in supporting
12ff7e0accSmrgdocumentation.
13ff7e0accSmrg
14ff7e0accSmrgThe above copyright notice and this permission notice shall be included
15ff7e0accSmrgin all copies or substantial portions of the Software.
16ff7e0accSmrg
17ff7e0accSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18ff7e0accSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19ff7e0accSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
20ff7e0accSmrgOF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21ff7e0accSmrgHOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
22ff7e0accSmrgINDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
23ff7e0accSmrgFROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24ff7e0accSmrgNEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25ff7e0accSmrgWITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26ff7e0accSmrg
27ff7e0accSmrgExcept as contained in this notice, the name of a copyright holder
28ff7e0accSmrgshall not be used in advertising or otherwise to promote the sale, use
29ff7e0accSmrgor other dealings in this Software without prior written authorization
30ff7e0accSmrgof the copyright holder.
31ff7e0accSmrg
32ff7e0accSmrg*/
33ff7e0accSmrg/* $XFree86: xc/programs/xwininfo/xwininfo.c,v 1.9 2003/09/09 22:08:25 herrb Exp $ */
34ff7e0accSmrg
35ff7e0accSmrg
36ff7e0accSmrg/*
37ff7e0accSmrg * xwininfo.c	- MIT Project Athena, X Window system window
38ff7e0accSmrg *		  information utility.
39ff7e0accSmrg *
40ff7e0accSmrg *
41ff7e0accSmrg *	This program will report all relevant information
42ff7e0accSmrg *	about a specific window.
43ff7e0accSmrg *
44ff7e0accSmrg *  Author:	Mark Lillibridge, MIT Project Athena
45ff7e0accSmrg *		16-Jun-87
46ff7e0accSmrg */
47ff7e0accSmrg
48ff7e0accSmrg#include "config.h"
49ff7e0accSmrg#include <X11/Xlib.h>
50ff7e0accSmrg#include <X11/Xutil.h>
51ff7e0accSmrg#include <X11/Xatom.h>
52ff7e0accSmrg#include <X11/Xos.h>
53ff7e0accSmrg#include <X11/extensions/shape.h>
54ff7e0accSmrg#include <X11/Xmu/WinUtil.h>
55ff7e0accSmrg#ifndef NO_I18N
56ff7e0accSmrg#include <X11/Xlocale.h>
57ff7e0accSmrg#endif
58ff7e0accSmrg#include <stdio.h>
59ff7e0accSmrg#include <stdlib.h>
60ff7e0accSmrg
61ff7e0accSmrg/* Include routines to handle parsing defaults */
62ff7e0accSmrg#include "dsimple.h"
63ff7e0accSmrg
64ff7e0accSmrgtypedef struct {
65ff7e0accSmrg	long code;
66ff7e0accSmrg	const char *name;
67ff7e0accSmrg} binding;
68ff7e0accSmrg
69ff7e0accSmrgstatic void scale_init(void);
70ff7e0accSmrgstatic char *nscale(int, int, int, char *, size_t);
71ff7e0accSmrgstatic char *xscale(int);
72ff7e0accSmrgstatic char *yscale(int);
73ff7e0accSmrgstatic char *bscale(int);
74ff7e0accSmrgstatic int bad_window_handler(Display *, XErrorEvent *);
75ff7e0accSmrgint main(int, char **);
76ff7e0accSmrgstatic const char *LookupL(long, const binding *);
77ff7e0accSmrgstatic const char *Lookup(int, const binding *);
78ff7e0accSmrgstatic void Display_Window_Id(Window, int);
79ff7e0accSmrgstatic void Display_Stats_Info(Window);
80ff7e0accSmrgstatic void Display_Bits_Info(Window);
81ff7e0accSmrgstatic void Display_Event_Mask(long);
82ff7e0accSmrgstatic void Display_Events_Info(Window);
83ff7e0accSmrgstatic void Display_Tree_Info(Window, int);
84ff7e0accSmrgstatic void display_tree_info_1(Window, int, int);
85ff7e0accSmrgstatic void Display_Hints(XSizeHints *);
86ff7e0accSmrgstatic void Display_Size_Hints(Window);
87ff7e0accSmrgstatic void Display_Window_Shape(Window);
88ff7e0accSmrgstatic void Display_WM_Info(Window);
89ff7e0accSmrg
90ff7e0accSmrgstatic char *window_id_format = "0x%lx";
91ff7e0accSmrg
92ff7e0accSmrg#ifndef HAVE_STRLCAT
93ff7e0accSmrgstatic size_t strlcat(char *dst, const char *src, size_t dstsize)
94ff7e0accSmrg{
95ff7e0accSmrg    size_t sd = strlen(dst);
96ff7e0accSmrg    size_t ss = strlen(src);
97ff7e0accSmrg    size_t s = sd + ss;
98ff7e0accSmrg
99ff7e0accSmrg    if (s < dstsize) {
100ff7e0accSmrg	strcpy(dst + sd, src);
101ff7e0accSmrg    } else {
102ff7e0accSmrg	strncpy(dst + sd, src, dstsize-sd-1);
103ff7e0accSmrg	dst[dstsize] = '\0';
104ff7e0accSmrg    }
105ff7e0accSmrg    return s;
106ff7e0accSmrg}
107ff7e0accSmrg#endif
108ff7e0accSmrg
109ff7e0accSmrg/*
110ff7e0accSmrg * Report the syntax for calling xwininfo:
111ff7e0accSmrg */
112ff7e0accSmrgvoid
113ff7e0accSmrgusage(void)
114ff7e0accSmrg{
115ff7e0accSmrg    fprintf (stderr,
116ff7e0accSmrg	"usage:  %s [-options ...]\n\n", program_name);
117ff7e0accSmrg    fprintf (stderr,
118ff7e0accSmrg	"where options include:\n");
119ff7e0accSmrg    fprintf (stderr,
120ff7e0accSmrg	"    -help                print this message\n");
121ff7e0accSmrg    fprintf (stderr,
122ff7e0accSmrg	"    -display host:dpy    X server to contact\n");
123ff7e0accSmrg    fprintf (stderr,
124ff7e0accSmrg	"    -root                use the root window\n");
125ff7e0accSmrg    fprintf (stderr,
126ff7e0accSmrg	"    -id windowid         use the window with the specified id\n");
127ff7e0accSmrg    fprintf (stderr,
128ff7e0accSmrg	"    -name windowname     use the window with the specified name\n");
129ff7e0accSmrg    fprintf (stderr,
130ff7e0accSmrg	"    -int                 print window id in decimal\n");
131ff7e0accSmrg    fprintf (stderr,
132ff7e0accSmrg	"    -children            print parent and child identifiers\n");
133ff7e0accSmrg    fprintf (stderr,
134ff7e0accSmrg	"    -tree                print children identifiers recursively\n");
135ff7e0accSmrg    fprintf (stderr,
136ff7e0accSmrg	"    -stats               print window geometry [DEFAULT]\n");
137ff7e0accSmrg    fprintf (stderr,
138ff7e0accSmrg	"    -bits                print window pixel information\n");
139ff7e0accSmrg    fprintf (stderr,
140ff7e0accSmrg	"    -events              print events selected for on window\n");
141ff7e0accSmrg    fprintf (stderr,
142ff7e0accSmrg	"    -size                print size hints\n");
143ff7e0accSmrg    fprintf (stderr,
144ff7e0accSmrg	"    -wm                  print window manager hints\n");
145ff7e0accSmrg    fprintf (stderr,
146ff7e0accSmrg	"    -shape               print shape extents\n");
147ff7e0accSmrg    fprintf (stderr,
148ff7e0accSmrg	"    -frame               don't ignore window manager frames\n");
149ff7e0accSmrg    fprintf (stderr,
150ff7e0accSmrg	"    -english             print sizes in english units\n");
151ff7e0accSmrg    fprintf (stderr,
152ff7e0accSmrg	"    -metric              print sizes in metric units\n");
153ff7e0accSmrg    fprintf (stderr,
154ff7e0accSmrg	"    -all                 -tree, -stats, -bits, -events, -wm, -size, -shape\n");
155ff7e0accSmrg    fprintf (stderr,
156ff7e0accSmrg	"\n");
157ff7e0accSmrg    exit (1);
158ff7e0accSmrg}
159ff7e0accSmrg
160ff7e0accSmrg/*
161ff7e0accSmrg * pixel to inch, metric converter.
162ff7e0accSmrg * Hacked in by Mark W. Eichin <eichin@athena> [eichin:19880619.1509EST]
163ff7e0accSmrg *
164ff7e0accSmrg * Simply put: replace the old numbers with string print calls.
165ff7e0accSmrg * Returning a local string is ok, since we only ever get called to
166ff7e0accSmrg * print one x and one y, so as long as they don't collide, they're
167ff7e0accSmrg * fine. This is not meant to be a general purpose routine.
168ff7e0accSmrg *
169ff7e0accSmrg */
170ff7e0accSmrg
171ff7e0accSmrg#define getdsp(var,fn) var = fn(dpy, DefaultScreen(dpy))
172ff7e0accSmrgstatic int xp=0, xmm=0;
173ff7e0accSmrgstatic int yp=0, ymm=0;
174ff7e0accSmrgstatic int bp=0, bmm=0;
175ff7e0accSmrgstatic int english = 0, metric = 0;
176ff7e0accSmrg
177ff7e0accSmrgstatic void
178ff7e0accSmrgscale_init(void)
179ff7e0accSmrg{
180ff7e0accSmrg  getdsp(yp,  DisplayHeight);
181ff7e0accSmrg  getdsp(ymm, DisplayHeightMM);
182ff7e0accSmrg  getdsp(xp,  DisplayWidth);
183ff7e0accSmrg  getdsp(xmm, DisplayWidthMM);
184ff7e0accSmrg  bp  = xp  + yp;
185ff7e0accSmrg  bmm = xmm + ymm;
186ff7e0accSmrg}
187ff7e0accSmrg
188ff7e0accSmrg#define MILE (5280*12)
189ff7e0accSmrg#define YARD (3*12)
190ff7e0accSmrg#define FOOT (12)
191ff7e0accSmrg
192ff7e0accSmrgstatic char *
193ff7e0accSmrgnscale(int n, int np, int nmm, char *nbuf, size_t nbufsize)
194ff7e0accSmrg{
195ff7e0accSmrg    int s;
196ff7e0accSmrg    snprintf(nbuf, nbufsize, "%d", n);
197ff7e0accSmrg
198ff7e0accSmrg    if (metric||english) {
199ff7e0accSmrg	s = strlcat(nbuf, " (", nbufsize);
200ff7e0accSmrg
201ff7e0accSmrg	if (metric) {
202ff7e0accSmrg	    snprintf(nbuf+s, nbufsize-s, "%.2f mm%s",
203ff7e0accSmrg		     ((double) n)*nmm/np, english ? "; " : "");
204ff7e0accSmrg	}
205ff7e0accSmrg	if (english) {
206ff7e0accSmrg	    double inch_frac;
207ff7e0accSmrg	    Bool printed_anything = False;
208ff7e0accSmrg	    int mi, yar, ft, inr;
209ff7e0accSmrg
210ff7e0accSmrg	    inch_frac = ((double) n)*(nmm/25.4)/np;
211ff7e0accSmrg	    inr = (int)inch_frac;
212ff7e0accSmrg	    inch_frac -= (double)inr;
213ff7e0accSmrg	    if (inr >= MILE) {
214ff7e0accSmrg		mi = inr/MILE;
215ff7e0accSmrg		inr %= MILE;
216ff7e0accSmrg		s = strlen(nbuf);
217ff7e0accSmrg		snprintf(nbuf+s, nbufsize-s, "%d %s(?!?)",
218ff7e0accSmrg			 mi, (mi==1) ? "mile" : "miles");
219ff7e0accSmrg		printed_anything = True;
220ff7e0accSmrg	    }
221ff7e0accSmrg	    if (inr >= YARD) {
222ff7e0accSmrg		yar = inr/YARD;
223ff7e0accSmrg		inr %= YARD;
224ff7e0accSmrg		if (printed_anything)
225ff7e0accSmrg		    strlcat(nbuf, ", ", nbufsize);
226ff7e0accSmrg		s = strlen(nbuf);
227ff7e0accSmrg		snprintf(nbuf+s, nbufsize-s, "%d %s",
228ff7e0accSmrg			yar, (yar==1) ? "yard" : "yards");
229ff7e0accSmrg		printed_anything = True;
230ff7e0accSmrg	    }
231ff7e0accSmrg	    if (inr >= FOOT) {
232ff7e0accSmrg		ft = inr/FOOT;
233ff7e0accSmrg		inr  %= FOOT;
234ff7e0accSmrg		if (printed_anything)
235ff7e0accSmrg		    strlcat(nbuf, ", ", nbufsize);
236ff7e0accSmrg		s = strlen(nbuf);
237ff7e0accSmrg		snprintf(nbuf+s, nbufsize-s, "%d %s",
238ff7e0accSmrg			ft, (ft==1) ? "foot" : "feet");
239ff7e0accSmrg		printed_anything = True;
240ff7e0accSmrg	    }
241ff7e0accSmrg	    if (!printed_anything || inch_frac != 0.0 || inr != 0) {
242ff7e0accSmrg		if (printed_anything)
243ff7e0accSmrg		    strlcat(nbuf, ", ", nbufsize);
244ff7e0accSmrg		s = strlen(nbuf);
245ff7e0accSmrg		snprintf(nbuf+s, nbufsize-s, "%.2f inches", inr+inch_frac);
246ff7e0accSmrg	    }
247ff7e0accSmrg	}
248ff7e0accSmrg	strlcat (nbuf, ")", nbufsize);
249ff7e0accSmrg    }
250ff7e0accSmrg    return(nbuf);
251ff7e0accSmrg}
252ff7e0accSmrg
253ff7e0accSmrgstatic char xbuf[BUFSIZ];
254ff7e0accSmrgstatic char *
255ff7e0accSmrgxscale(int x)
256ff7e0accSmrg{
257ff7e0accSmrg  if(!xp) {
258ff7e0accSmrg    scale_init();
259ff7e0accSmrg  }
260ff7e0accSmrg  return(nscale(x, xp, xmm, xbuf, sizeof(xbuf)));
261ff7e0accSmrg}
262ff7e0accSmrg
263ff7e0accSmrgstatic char ybuf[BUFSIZ];
264ff7e0accSmrgstatic char *
265ff7e0accSmrgyscale(int y)
266ff7e0accSmrg{
267ff7e0accSmrg  if(!yp) {
268ff7e0accSmrg    scale_init();
269ff7e0accSmrg  }
270ff7e0accSmrg  return(nscale(y, yp, ymm, ybuf, sizeof(ybuf)));
271ff7e0accSmrg}
272ff7e0accSmrg
273ff7e0accSmrgstatic char bbuf[BUFSIZ];
274ff7e0accSmrgstatic char *
275ff7e0accSmrgbscale(int b)
276ff7e0accSmrg{
277ff7e0accSmrg  if(!bp) {
278ff7e0accSmrg    scale_init();
279ff7e0accSmrg  }
280ff7e0accSmrg  return(nscale(b, bp, bmm, bbuf, sizeof(bbuf)));
281ff7e0accSmrg}
282ff7e0accSmrg
283ff7e0accSmrg/* end of pixel to inch, metric converter */
284ff7e0accSmrg
285ff7e0accSmrg/* This handler is enabled when we are checking
286ff7e0accSmrg   to see if the -id the user specified is valid. */
287ff7e0accSmrg
288ff7e0accSmrg/* ARGSUSED */
289ff7e0accSmrgstatic int
290ff7e0accSmrgbad_window_handler(Display *disp, XErrorEvent *err)
291ff7e0accSmrg{
292ff7e0accSmrg    char badid[20];
293ff7e0accSmrg
294ff7e0accSmrg    snprintf(badid, sizeof(badid), window_id_format, err->resourceid);
295ff7e0accSmrg    Fatal_Error("No such window with id %s.", badid);
296ff7e0accSmrg    exit (1);
297ff7e0accSmrg    return 0;
298ff7e0accSmrg}
299ff7e0accSmrg
300ff7e0accSmrg
301ff7e0accSmrgint
302ff7e0accSmrgmain(int argc, char **argv)
303ff7e0accSmrg{
304ff7e0accSmrg  register int i;
305ff7e0accSmrg  int tree = 0, stats = 0, bits = 0, events = 0, wm = 0, size  = 0, shape = 0;
306ff7e0accSmrg  int frame = 0, children = 0;
307ff7e0accSmrg  Window window;
308ff7e0accSmrg
309ff7e0accSmrg  INIT_NAME;
310ff7e0accSmrg
311ff7e0accSmrg#ifndef NO_I18N
312ff7e0accSmrg  {
313ff7e0accSmrg     char *lc;
314ff7e0accSmrg     lc = setlocale(LC_ALL, "");
315ff7e0accSmrg     if(!lc)
316ff7e0accSmrg        fprintf(stderr, "can not set locale properly\n");
317ff7e0accSmrg  }
318ff7e0accSmrg#endif
319ff7e0accSmrg
320ff7e0accSmrg  /* Open display, handle command line arguments */
321ff7e0accSmrg  Setup_Display_And_Screen(&argc, argv);
322ff7e0accSmrg
323ff7e0accSmrg  /* Get window selected on command line, if any */
324ff7e0accSmrg  window = Select_Window_Args(&argc, argv);
325ff7e0accSmrg
326ff7e0accSmrg  /* Handle our command line arguments */
327ff7e0accSmrg  for (i = 1; i < argc; i++) {
328ff7e0accSmrg    if (!strcmp(argv[i], "-help"))
329ff7e0accSmrg      usage();
330ff7e0accSmrg    if (!strcmp(argv[i], "-int")) {
331ff7e0accSmrg      window_id_format = "%ld";
332ff7e0accSmrg      continue;
333ff7e0accSmrg    }
334ff7e0accSmrg    if (!strcmp(argv[i], "-children")) {
335ff7e0accSmrg      children = 1;
336ff7e0accSmrg      continue;
337ff7e0accSmrg    }
338ff7e0accSmrg    if (!strcmp(argv[i], "-tree")) {
339ff7e0accSmrg      tree = 1;
340ff7e0accSmrg      continue;
341ff7e0accSmrg    }
342ff7e0accSmrg    if (!strcmp(argv[i], "-stats")) {
343ff7e0accSmrg      stats = 1;
344ff7e0accSmrg      continue;
345ff7e0accSmrg    }
346ff7e0accSmrg    if (!strcmp(argv[i], "-bits")) {
347ff7e0accSmrg      bits = 1;
348ff7e0accSmrg      continue;
349ff7e0accSmrg    }
350ff7e0accSmrg    if (!strcmp(argv[i], "-events")) {
351ff7e0accSmrg      events = 1;
352ff7e0accSmrg      continue;
353ff7e0accSmrg    }
354ff7e0accSmrg    if (!strcmp(argv[i], "-wm")) {
355ff7e0accSmrg      wm = 1;
356ff7e0accSmrg      continue;
357ff7e0accSmrg    }
358ff7e0accSmrg    if (!strcmp(argv[i], "-frame")) {
359ff7e0accSmrg      frame = 1;
360ff7e0accSmrg      continue;
361ff7e0accSmrg    }
362ff7e0accSmrg    if (!strcmp(argv[i], "-size")) {
363ff7e0accSmrg      size = 1;
364ff7e0accSmrg      continue;
365ff7e0accSmrg    }
366ff7e0accSmrg    if (!strcmp(argv[i], "-shape")) {
367ff7e0accSmrg      shape = 1;
368ff7e0accSmrg      continue;
369ff7e0accSmrg    }
370ff7e0accSmrg    if (!strcmp(argv[i], "-english")) {
371ff7e0accSmrg      english = 1;
372ff7e0accSmrg      continue;
373ff7e0accSmrg    }
374ff7e0accSmrg    if (!strcmp(argv[i], "-metric")) {
375ff7e0accSmrg      metric = 1;
376ff7e0accSmrg      continue;
377ff7e0accSmrg    }
378ff7e0accSmrg    if (!strcmp(argv[i], "-all")) {
379ff7e0accSmrg      tree = stats = bits = events = wm = size = shape = 1;
380ff7e0accSmrg      continue;
381ff7e0accSmrg    }
382ff7e0accSmrg    usage();
383ff7e0accSmrg  }
384ff7e0accSmrg
385ff7e0accSmrg  /* If no window selected on command line, let user pick one the hard way */
386ff7e0accSmrg  if (!window) {
387ff7e0accSmrg	  printf("\n");
388ff7e0accSmrg	  printf("xwininfo: Please select the window about which you\n");
389ff7e0accSmrg	  printf("          would like information by clicking the\n");
390ff7e0accSmrg	  printf("          mouse in that window.\n");
391ff7e0accSmrg	  window = Select_Window(dpy);
392ff7e0accSmrg	  if (window && !frame) {
393ff7e0accSmrg	      Window root;
394ff7e0accSmrg	      int dummyi;
395ff7e0accSmrg	      unsigned int dummy;
396ff7e0accSmrg
397ff7e0accSmrg	      if (XGetGeometry (dpy, window, &root, &dummyi, &dummyi,
398ff7e0accSmrg				&dummy, &dummy, &dummy, &dummy) &&
399ff7e0accSmrg		  window != root)
400ff7e0accSmrg	        window = XmuClientWindow (dpy, window);
401ff7e0accSmrg	  }
402ff7e0accSmrg  }
403ff7e0accSmrg
404ff7e0accSmrg  /*
405ff7e0accSmrg   * Do the actual displaying as per parameters
406ff7e0accSmrg   */
407ff7e0accSmrg  if (!(children || tree || bits || events || wm || size))
408ff7e0accSmrg    stats = 1;
409ff7e0accSmrg
410ff7e0accSmrg  /*
411ff7e0accSmrg   * make sure that the window is valid
412ff7e0accSmrg   */
413ff7e0accSmrg  {
414ff7e0accSmrg    Window root;
415ff7e0accSmrg    int x, y;
416ff7e0accSmrg    unsigned width, height, bw, depth;
417ff7e0accSmrg    XErrorHandler old_handler;
418ff7e0accSmrg
419ff7e0accSmrg    old_handler = XSetErrorHandler(bad_window_handler);
420ff7e0accSmrg    XGetGeometry (dpy, window, &root, &x, &y, &width, &height, &bw, &depth);
421ff7e0accSmrg    XSync (dpy, False);
422ff7e0accSmrg    (void) XSetErrorHandler(old_handler);
423ff7e0accSmrg  }
424ff7e0accSmrg
425ff7e0accSmrg  printf("\nxwininfo: Window id: ");
426ff7e0accSmrg  Display_Window_Id(window, True);
427ff7e0accSmrg  if (children || tree)
428ff7e0accSmrg    Display_Tree_Info(window, tree);
429ff7e0accSmrg  if (stats)
430ff7e0accSmrg    Display_Stats_Info(window);
431ff7e0accSmrg  if (bits)
432ff7e0accSmrg    Display_Bits_Info(window);
433ff7e0accSmrg  if (events)
434ff7e0accSmrg    Display_Events_Info(window);
435ff7e0accSmrg  if (wm)
436ff7e0accSmrg    Display_WM_Info(window);
437ff7e0accSmrg  if (size)
438ff7e0accSmrg    Display_Size_Hints(window);
439ff7e0accSmrg  if (shape)
440ff7e0accSmrg    Display_Window_Shape(window);
441ff7e0accSmrg  printf("\n");
442ff7e0accSmrg  exit(0);
443ff7e0accSmrg}
444ff7e0accSmrg
445ff7e0accSmrg
446ff7e0accSmrg/*
447ff7e0accSmrg * Lookup: lookup a code in a table.
448ff7e0accSmrg */
449ff7e0accSmrgstatic char _lookup_buffer[100];
450ff7e0accSmrg
451ff7e0accSmrgstatic const char *
452ff7e0accSmrgLookupL(long code, const binding *table)
453ff7e0accSmrg{
454ff7e0accSmrg	const char *name;
455ff7e0accSmrg
456ff7e0accSmrg	snprintf(_lookup_buffer, sizeof(_lookup_buffer),
457ff7e0accSmrg		 "unknown (code = %ld. = 0x%lx)", code, code);
458ff7e0accSmrg	name = _lookup_buffer;
459ff7e0accSmrg
460ff7e0accSmrg	while (table->name) {
461ff7e0accSmrg		if (table->code == code) {
462ff7e0accSmrg			name = table->name;
463ff7e0accSmrg			break;
464ff7e0accSmrg		}
465ff7e0accSmrg		table++;
466ff7e0accSmrg	}
467ff7e0accSmrg
468ff7e0accSmrg	return(name);
469ff7e0accSmrg}
470ff7e0accSmrg
471ff7e0accSmrgstatic const char *
472ff7e0accSmrgLookup(int code, const binding *table)
473ff7e0accSmrg{
474ff7e0accSmrg    return LookupL((long)code, table);
475ff7e0accSmrg}
476ff7e0accSmrg
477ff7e0accSmrg/*
478ff7e0accSmrg * Routine to display a window id in dec/hex with name if window has one
479ff7e0accSmrg */
480ff7e0accSmrg
481ff7e0accSmrgstatic void
482ff7e0accSmrgDisplay_Window_Id(Window window, Bool newline_wanted)
483ff7e0accSmrg{
484ff7e0accSmrg#ifdef NO_I18N
485ff7e0accSmrg    char *win_name;
486ff7e0accSmrg#else
487ff7e0accSmrg    XTextProperty tp;
488ff7e0accSmrg#endif
489ff7e0accSmrg
490ff7e0accSmrg    printf(window_id_format, window);         /* print id # in hex/dec */
491ff7e0accSmrg
492ff7e0accSmrg    if (!window) {
493ff7e0accSmrg	printf(" (none)");
494ff7e0accSmrg    } else {
495ff7e0accSmrg	if (window == RootWindow(dpy, screen)) {
496ff7e0accSmrg	    printf(" (the root window)");
497ff7e0accSmrg	}
498ff7e0accSmrg#ifdef NO_I18N
499ff7e0accSmrg	if (!XFetchName(dpy, window, &win_name)) { /* Get window name if any */
500ff7e0accSmrg	    printf(" (has no name)");
501ff7e0accSmrg	} else if (win_name) {
502ff7e0accSmrg	    printf(" \"%s\"", win_name);
503ff7e0accSmrg	    XFree(win_name);
504ff7e0accSmrg	}
505ff7e0accSmrg#else
506ff7e0accSmrg	if (!XGetWMName(dpy, window, &tp)) { /* Get window name if any */
507ff7e0accSmrg	    printf(" (has no name)");
508ff7e0accSmrg        } else if (tp.nitems > 0) {
509ff7e0accSmrg            printf(" \"");
510ff7e0accSmrg            {
511ff7e0accSmrg                int count = 0, i, ret;
512ff7e0accSmrg                char **list = NULL;
513ff7e0accSmrg                ret = XmbTextPropertyToTextList(dpy, &tp, &list, &count);
514ff7e0accSmrg                if((ret == Success || ret > 0) && list != NULL){
515ff7e0accSmrg                    for(i=0; i<count; i++)
516ff7e0accSmrg                        printf("%s", list[i]);
517ff7e0accSmrg                    XFreeStringList(list);
518ff7e0accSmrg                } else {
519ff7e0accSmrg                    printf("%s", tp.value);
520ff7e0accSmrg                }
521ff7e0accSmrg            }
522ff7e0accSmrg            printf("\"");
523ff7e0accSmrg	}
524ff7e0accSmrg#endif
525ff7e0accSmrg	else
526ff7e0accSmrg	    printf(" (has no name)");
527ff7e0accSmrg    }
528ff7e0accSmrg
529ff7e0accSmrg    if (newline_wanted)
530ff7e0accSmrg	printf("\n");
531ff7e0accSmrg
532ff7e0accSmrg    return;
533ff7e0accSmrg}
534ff7e0accSmrg
535ff7e0accSmrg
536ff7e0accSmrg/*
537ff7e0accSmrg * Display Stats on window
538ff7e0accSmrg */
539ff7e0accSmrgstatic const binding _window_classes[] = {
540ff7e0accSmrg	{ InputOutput, "InputOutput" },
541ff7e0accSmrg	{ InputOnly, "InputOnly" },
542ff7e0accSmrg        { 0, 0 } };
543ff7e0accSmrg
544ff7e0accSmrgstatic const binding _map_states[] = {
545ff7e0accSmrg	{ IsUnmapped, "IsUnMapped" },
546ff7e0accSmrg	{ IsUnviewable, "IsUnviewable" },
547ff7e0accSmrg	{ IsViewable, "IsViewable" },
548ff7e0accSmrg	{ 0, 0 } };
549ff7e0accSmrg
550ff7e0accSmrgstatic const binding _backing_store_states[] = {
551ff7e0accSmrg	{ NotUseful, "NotUseful" },
552ff7e0accSmrg	{ WhenMapped, "WhenMapped" },
553ff7e0accSmrg	{ Always, "Always" },
554ff7e0accSmrg	{ 0, 0 } };
555ff7e0accSmrg
556ff7e0accSmrgstatic const binding _bit_gravity_states[] = {
557ff7e0accSmrg	{ ForgetGravity, "ForgetGravity" },
558ff7e0accSmrg	{ NorthWestGravity, "NorthWestGravity" },
559ff7e0accSmrg	{ NorthGravity, "NorthGravity" },
560ff7e0accSmrg	{ NorthEastGravity, "NorthEastGravity" },
561ff7e0accSmrg	{ WestGravity, "WestGravity" },
562ff7e0accSmrg	{ CenterGravity, "CenterGravity" },
563ff7e0accSmrg	{ EastGravity, "EastGravity" },
564ff7e0accSmrg	{ SouthWestGravity, "SouthWestGravity" },
565ff7e0accSmrg	{ SouthGravity, "SouthGravity" },
566ff7e0accSmrg	{ SouthEastGravity, "SouthEastGravity" },
567ff7e0accSmrg	{ StaticGravity, "StaticGravity" },
568ff7e0accSmrg	{ 0, 0 }};
569ff7e0accSmrg
570ff7e0accSmrgstatic const binding _window_gravity_states[] = {
571ff7e0accSmrg	{ UnmapGravity, "UnmapGravity" },
572ff7e0accSmrg	{ NorthWestGravity, "NorthWestGravity" },
573ff7e0accSmrg	{ NorthGravity, "NorthGravity" },
574ff7e0accSmrg	{ NorthEastGravity, "NorthEastGravity" },
575ff7e0accSmrg	{ WestGravity, "WestGravity" },
576ff7e0accSmrg	{ CenterGravity, "CenterGravity" },
577ff7e0accSmrg	{ EastGravity, "EastGravity" },
578ff7e0accSmrg	{ SouthWestGravity, "SouthWestGravity" },
579ff7e0accSmrg	{ SouthGravity, "SouthGravity" },
580ff7e0accSmrg	{ SouthEastGravity, "SouthEastGravity" },
581ff7e0accSmrg	{ StaticGravity, "StaticGravity" },
582ff7e0accSmrg	{ 0, 0 }};
583ff7e0accSmrg
584ff7e0accSmrgstatic const binding _visual_classes[] = {
585ff7e0accSmrg	{ StaticGray, "StaticGray" },
586ff7e0accSmrg	{ GrayScale, "GrayScale" },
587ff7e0accSmrg	{ StaticColor, "StaticColor" },
588ff7e0accSmrg	{ PseudoColor, "PseudoColor" },
589ff7e0accSmrg	{ TrueColor, "TrueColor" },
590ff7e0accSmrg	{ DirectColor, "DirectColor" },
591ff7e0accSmrg	{ 0, 0 }};
592ff7e0accSmrg
593ff7e0accSmrgstatic void
594ff7e0accSmrgDisplay_Stats_Info(Window window)
595ff7e0accSmrg{
596ff7e0accSmrg  XWindowAttributes win_attributes;
597ff7e0accSmrg  XVisualInfo vistemplate, *vinfo;
598ff7e0accSmrg  XSizeHints hints;
599ff7e0accSmrg  int dw = DisplayWidth (dpy, screen), dh = DisplayHeight (dpy, screen);
600ff7e0accSmrg  int rx, ry, xright, ybelow;
601ff7e0accSmrg  int showright = 0, showbelow = 0;
602ff7e0accSmrg  Status status;
603ff7e0accSmrg  Window wmframe;
604ff7e0accSmrg  int junk;
605ff7e0accSmrg  long longjunk;
606ff7e0accSmrg  Window junkwin;
607ff7e0accSmrg
608ff7e0accSmrg  if (!XGetWindowAttributes(dpy, window, &win_attributes))
609ff7e0accSmrg    Fatal_Error("Can't get window attributes.");
610ff7e0accSmrg  vistemplate.visualid = XVisualIDFromVisual(win_attributes.visual);
611ff7e0accSmrg  vinfo = XGetVisualInfo(dpy, VisualIDMask, &vistemplate, &junk);
612ff7e0accSmrg
613ff7e0accSmrg  (void) XTranslateCoordinates (dpy, window, win_attributes.root,
614ff7e0accSmrg				-win_attributes.border_width,
615ff7e0accSmrg				-win_attributes.border_width,
616ff7e0accSmrg				&rx, &ry, &junkwin);
617ff7e0accSmrg
618ff7e0accSmrg  xright = (dw - rx - win_attributes.border_width * 2 -
619ff7e0accSmrg	    win_attributes.width);
620ff7e0accSmrg  ybelow = (dh - ry - win_attributes.border_width * 2 -
621ff7e0accSmrg	    win_attributes.height);
622ff7e0accSmrg
623ff7e0accSmrg  printf("\n");
624ff7e0accSmrg  printf("  Absolute upper-left X:  %s\n", xscale(rx));
625ff7e0accSmrg  printf("  Absolute upper-left Y:  %s\n", yscale(ry));
626ff7e0accSmrg  printf("  Relative upper-left X:  %s\n", xscale(win_attributes.x));
627ff7e0accSmrg  printf("  Relative upper-left Y:  %s\n", yscale(win_attributes.y));
628ff7e0accSmrg  printf("  Width: %s\n", xscale(win_attributes.width));
629ff7e0accSmrg  printf("  Height: %s\n", yscale(win_attributes.height));
630ff7e0accSmrg  printf("  Depth: %d\n", win_attributes.depth);
631ff7e0accSmrg  printf("  Visual Class: %s\n", Lookup(vinfo->class, _visual_classes));
632ff7e0accSmrg  printf("  Border width: %s\n", bscale(win_attributes.border_width));
633ff7e0accSmrg  printf("  Class: %s\n",
634ff7e0accSmrg  	 Lookup(win_attributes.class, _window_classes));
635ff7e0accSmrg  printf("  Colormap: 0x%lx (%sinstalled)\n",
636ff7e0accSmrg	 win_attributes.colormap, win_attributes.map_installed ? "" : "not ");
637ff7e0accSmrg  printf("  Bit Gravity State: %s\n",
638ff7e0accSmrg  	 Lookup(win_attributes.bit_gravity, _bit_gravity_states));
639ff7e0accSmrg  printf("  Window Gravity State: %s\n",
640ff7e0accSmrg  	 Lookup(win_attributes.win_gravity, _window_gravity_states));
641ff7e0accSmrg  printf("  Backing Store State: %s\n",
642ff7e0accSmrg  	 Lookup(win_attributes.backing_store, _backing_store_states));
643ff7e0accSmrg  printf("  Save Under State: %s\n",
644ff7e0accSmrg  	 win_attributes.save_under ? "yes" : "no");
645ff7e0accSmrg  printf("  Map State: %s\n",
646ff7e0accSmrg	 Lookup(win_attributes.map_state, _map_states));
647ff7e0accSmrg  printf("  Override Redirect State: %s\n",
648ff7e0accSmrg  	 win_attributes.override_redirect ? "yes" : "no");
649ff7e0accSmrg  printf("  Corners:  +%d+%d  -%d+%d  -%d-%d  +%d-%d\n",
650ff7e0accSmrg	 rx, ry, xright, ry, xright, ybelow, rx, ybelow);
651ff7e0accSmrg
652ff7e0accSmrg  XFree(vinfo);
653ff7e0accSmrg
654ff7e0accSmrg  /*
655ff7e0accSmrg   * compute geometry string that would recreate window
656ff7e0accSmrg   */
657ff7e0accSmrg  printf("  -geometry ");
658ff7e0accSmrg
659ff7e0accSmrg  /* compute size in appropriate units */
660ff7e0accSmrg  status = XGetWMNormalHints(dpy, window, &hints, &longjunk);
661ff7e0accSmrg  if (status  &&  hints.flags & PResizeInc  &&
662ff7e0accSmrg              hints.width_inc != 0  &&  hints.height_inc != 0) {
663ff7e0accSmrg      if (hints.flags & (PBaseSize|PMinSize)) {
664ff7e0accSmrg	  if (hints.flags & PBaseSize) {
665ff7e0accSmrg	      win_attributes.width -= hints.base_width;
666ff7e0accSmrg	      win_attributes.height -= hints.base_height;
667ff7e0accSmrg	  } else {
668ff7e0accSmrg	      /* ICCCM says MinSize is default for BaseSize */
669ff7e0accSmrg	      win_attributes.width -= hints.min_width;
670ff7e0accSmrg	      win_attributes.height -= hints.min_height;
671ff7e0accSmrg	  }
672ff7e0accSmrg      }
673ff7e0accSmrg      printf("%dx%d", win_attributes.width/hints.width_inc,
674ff7e0accSmrg	     win_attributes.height/hints.height_inc);
675ff7e0accSmrg  } else
676ff7e0accSmrg      printf("%dx%d", win_attributes.width, win_attributes.height);
677ff7e0accSmrg
678ff7e0accSmrg  if (!(hints.flags&PWinGravity))
679ff7e0accSmrg      hints.win_gravity = NorthWestGravity; /* per ICCCM */
680ff7e0accSmrg  /* find our window manager frame, if any */
681ff7e0accSmrg  wmframe = window;
682ff7e0accSmrg  while (True) {
683ff7e0accSmrg      Window root, parent;
684ff7e0accSmrg      Window *childlist;
685ff7e0accSmrg      unsigned int ujunk;
686ff7e0accSmrg
687ff7e0accSmrg      status = XQueryTree(dpy, wmframe, &root, &parent, &childlist, &ujunk);
688ff7e0accSmrg      if (parent == root || !parent || !status)
689ff7e0accSmrg	  break;
690ff7e0accSmrg      wmframe = parent;
691ff7e0accSmrg      if (status && childlist)
692ff7e0accSmrg	  XFree((char *)childlist);
693ff7e0accSmrg  }
694ff7e0accSmrg  if (wmframe != window) {
695ff7e0accSmrg      /* WM reparented, so find edges of the frame */
696ff7e0accSmrg      /* Only works for ICCCM-compliant WMs, and then only if the
697ff7e0accSmrg         window has corner gravity.  We would need to know the original width
698ff7e0accSmrg	 of the window to correctly handle the other gravities. */
699ff7e0accSmrg
700ff7e0accSmrg      XWindowAttributes frame_attr;
701ff7e0accSmrg
702ff7e0accSmrg      if (!XGetWindowAttributes(dpy, wmframe, &frame_attr))
703ff7e0accSmrg	  Fatal_Error("Can't get frame attributes.");
704ff7e0accSmrg      switch (hints.win_gravity) {
705ff7e0accSmrg	case NorthWestGravity: case SouthWestGravity:
706ff7e0accSmrg	case NorthEastGravity: case SouthEastGravity:
707ff7e0accSmrg	case WestGravity:
708ff7e0accSmrg	  rx = frame_attr.x;
709ff7e0accSmrg      }
710ff7e0accSmrg      switch (hints.win_gravity) {
711ff7e0accSmrg	case NorthWestGravity: case SouthWestGravity:
712ff7e0accSmrg	case NorthEastGravity: case SouthEastGravity:
713ff7e0accSmrg	case EastGravity:
714ff7e0accSmrg	  xright = dw - frame_attr.x - frame_attr.width -
715ff7e0accSmrg	      2*frame_attr.border_width;
716ff7e0accSmrg      }
717ff7e0accSmrg      switch (hints.win_gravity) {
718ff7e0accSmrg	case NorthWestGravity: case SouthWestGravity:
719ff7e0accSmrg	case NorthEastGravity: case SouthEastGravity:
720ff7e0accSmrg	case NorthGravity:
721ff7e0accSmrg	  ry = frame_attr.y;
722ff7e0accSmrg      }
723ff7e0accSmrg      switch (hints.win_gravity) {
724ff7e0accSmrg	case NorthWestGravity: case SouthWestGravity:
725ff7e0accSmrg	case NorthEastGravity: case SouthEastGravity:
726ff7e0accSmrg	case SouthGravity:
727ff7e0accSmrg	  ybelow = dh - frame_attr.y - frame_attr.height -
728ff7e0accSmrg	      2*frame_attr.border_width;
729ff7e0accSmrg      }
730ff7e0accSmrg  }
731ff7e0accSmrg  /* If edge gravity, offer a corner on that edge (because the application
732ff7e0accSmrg     programmer cares about that edge), otherwise offer upper left unless
733ff7e0accSmrg     some other corner is close to an edge of the screen.
734ff7e0accSmrg     (For corner gravity, assume gravity was set by XWMGeometry.
735ff7e0accSmrg     For CenterGravity, it doesn't matter.) */
736ff7e0accSmrg  if (hints.win_gravity == EastGravity  ||
737ff7e0accSmrg      (abs(xright) <= 100  &&  abs(xright) < abs(rx)
738ff7e0accSmrg        &&  hints.win_gravity != WestGravity))
739ff7e0accSmrg      showright = 1;
740ff7e0accSmrg  if (hints.win_gravity == SouthGravity  ||
741ff7e0accSmrg      (abs(ybelow) <= 100  &&  abs(ybelow) < abs(ry)
742ff7e0accSmrg        &&  hints.win_gravity != NorthGravity))
743ff7e0accSmrg      showbelow = 1;
744ff7e0accSmrg
745ff7e0accSmrg  if (showright)
746ff7e0accSmrg      printf("-%d", xright);
747ff7e0accSmrg  else
748ff7e0accSmrg      printf("+%d", rx);
749ff7e0accSmrg  if (showbelow)
750ff7e0accSmrg      printf("-%d", ybelow);
751ff7e0accSmrg  else
752ff7e0accSmrg      printf("+%d", ry);
753ff7e0accSmrg  printf("\n");
754ff7e0accSmrg}
755ff7e0accSmrg
756ff7e0accSmrg
757ff7e0accSmrg/*
758ff7e0accSmrg * Display bits info:
759ff7e0accSmrg */
760ff7e0accSmrgstatic const binding _gravities[] = {
761ff7e0accSmrg	{ UnmapGravity, "UnMapGravity" },      /* WARNING: both of these have*/
762ff7e0accSmrg	{ ForgetGravity, "ForgetGravity" },    /* the same value - see code */
763ff7e0accSmrg	{ NorthWestGravity, "NorthWestGravity" },
764ff7e0accSmrg	{ NorthGravity, "NorthGravity" },
765ff7e0accSmrg	{ NorthEastGravity, "NorthEastGravity" },
766ff7e0accSmrg	{ WestGravity, "WestGravity" },
767ff7e0accSmrg	{ CenterGravity, "CenterGravity" },
768ff7e0accSmrg	{ EastGravity, "EastGravity" },
769ff7e0accSmrg	{ SouthWestGravity, "SouthWestGravity" },
770ff7e0accSmrg	{ SouthGravity, "SouthGravity" },
771ff7e0accSmrg	{ SouthEastGravity, "SouthEastGravity" },
772ff7e0accSmrg	{ StaticGravity, "StaticGravity" },
773ff7e0accSmrg	{ 0, 0 } };
774ff7e0accSmrg
775ff7e0accSmrgstatic const binding _backing_store_hint[] = {
776ff7e0accSmrg	{ NotUseful, "NotUseful" },
777ff7e0accSmrg	{ WhenMapped, "WhenMapped" },
778ff7e0accSmrg	{ Always, "Always" },
779ff7e0accSmrg	{ 0, 0 } };
780ff7e0accSmrg
781ff7e0accSmrgstatic const binding _bool[] = {
782ff7e0accSmrg	{ 0, "No" },
783ff7e0accSmrg	{ 1, "Yes" },
784ff7e0accSmrg	{ 0, 0 } };
785ff7e0accSmrg
786ff7e0accSmrgstatic void
787ff7e0accSmrgDisplay_Bits_Info(Window window)
788ff7e0accSmrg{
789ff7e0accSmrg  XWindowAttributes win_attributes;
790ff7e0accSmrg
791ff7e0accSmrg  if (!XGetWindowAttributes(dpy, window, &win_attributes))
792ff7e0accSmrg    Fatal_Error("Can't get window attributes.");
793ff7e0accSmrg
794ff7e0accSmrg  printf("\n");
795ff7e0accSmrg  printf("  Bit gravity: %s\n",
796ff7e0accSmrg	 Lookup(win_attributes.bit_gravity, _gravities+1));
797ff7e0accSmrg  printf("  Window gravity: %s\n",
798ff7e0accSmrg	 Lookup(win_attributes.win_gravity, _gravities));
799ff7e0accSmrg  printf("  Backing-store hint: %s\n",
800ff7e0accSmrg	 Lookup(win_attributes.backing_store, _backing_store_hint));
801ff7e0accSmrg  printf("  Backing-planes to be preserved: 0x%lx\n",
802ff7e0accSmrg	 win_attributes.backing_planes);
803ff7e0accSmrg  printf("  Backing pixel: %ld\n", win_attributes.backing_pixel);
804ff7e0accSmrg  printf("  Save-unders: %s\n",
805ff7e0accSmrg	 Lookup(win_attributes.save_under, _bool));
806ff7e0accSmrg}
807ff7e0accSmrg
808ff7e0accSmrg
809ff7e0accSmrg/*
810ff7e0accSmrg * Routine to display all events in an event mask
811ff7e0accSmrg */
812ff7e0accSmrgstatic const binding _event_mask_names[] = {
813ff7e0accSmrg	{ KeyPressMask, "KeyPress" },
814ff7e0accSmrg	{ KeyReleaseMask, "KeyRelease" },
815ff7e0accSmrg	{ ButtonPressMask, "ButtonPress" },
816ff7e0accSmrg	{ ButtonReleaseMask, "ButtonRelease" },
817ff7e0accSmrg	{ EnterWindowMask, "EnterWindow" },
818ff7e0accSmrg	{ LeaveWindowMask, "LeaveWindow" },
819ff7e0accSmrg	{ PointerMotionMask, "PointerMotion" },
820ff7e0accSmrg	{ PointerMotionHintMask, "PointerMotionHint" },
821ff7e0accSmrg	{ Button1MotionMask, "Button1Motion" },
822ff7e0accSmrg	{ Button2MotionMask, "Button2Motion" },
823ff7e0accSmrg	{ Button3MotionMask, "Button3Motion" },
824ff7e0accSmrg	{ Button4MotionMask, "Button4Motion" },
825ff7e0accSmrg	{ Button5MotionMask, "Button5Motion" },
826ff7e0accSmrg	{ ButtonMotionMask, "ButtonMotion" },
827ff7e0accSmrg	{ KeymapStateMask, "KeymapState" },
828ff7e0accSmrg	{ ExposureMask, "Exposure" },
829ff7e0accSmrg	{ VisibilityChangeMask, "VisibilityChange" },
830ff7e0accSmrg	{ StructureNotifyMask, "StructureNotify" },
831ff7e0accSmrg	{ ResizeRedirectMask, "ResizeRedirect" },
832ff7e0accSmrg	{ SubstructureNotifyMask, "SubstructureNotify" },
833ff7e0accSmrg	{ SubstructureRedirectMask, "SubstructureRedirect" },
834ff7e0accSmrg	{ FocusChangeMask, "FocusChange" },
835ff7e0accSmrg	{ PropertyChangeMask, "PropertyChange" },
836ff7e0accSmrg	{ ColormapChangeMask, "ColormapChange" },
837ff7e0accSmrg	{ OwnerGrabButtonMask, "OwnerGrabButton" },
838ff7e0accSmrg	{ 0, 0 } };
839ff7e0accSmrg
840ff7e0accSmrgstatic void
841ff7e0accSmrgDisplay_Event_Mask(long mask)
842ff7e0accSmrg{
843ff7e0accSmrg  long bit, bit_mask;
844ff7e0accSmrg
845ff7e0accSmrg  for (bit=0, bit_mask=1; bit<sizeof(long)*8; bit++, bit_mask <<= 1)
846ff7e0accSmrg    if (mask & bit_mask)
847ff7e0accSmrg      printf("      %s\n",
848ff7e0accSmrg	     LookupL(bit_mask, _event_mask_names));
849ff7e0accSmrg}
850ff7e0accSmrg
851ff7e0accSmrg
852ff7e0accSmrg/*
853ff7e0accSmrg * Display info on events
854ff7e0accSmrg */
855ff7e0accSmrgstatic void
856ff7e0accSmrgDisplay_Events_Info(Window window)
857ff7e0accSmrg{
858ff7e0accSmrg  XWindowAttributes win_attributes;
859ff7e0accSmrg
860ff7e0accSmrg  if (!XGetWindowAttributes(dpy, window, &win_attributes))
861ff7e0accSmrg    Fatal_Error("Can't get window attributes.");
862ff7e0accSmrg
863ff7e0accSmrg  printf("\n");
864ff7e0accSmrg  printf("  Someone wants these events:\n");
865ff7e0accSmrg  Display_Event_Mask(win_attributes.all_event_masks);
866ff7e0accSmrg
867ff7e0accSmrg  printf("  Do not propagate these events:\n");
868ff7e0accSmrg  Display_Event_Mask(win_attributes.do_not_propagate_mask);
869ff7e0accSmrg
870ff7e0accSmrg  printf("  Override redirection?: %s\n",
871ff7e0accSmrg	 Lookup(win_attributes.override_redirect, _bool));
872ff7e0accSmrg}
873ff7e0accSmrg
874ff7e0accSmrg
875ff7e0accSmrg  /* left out visual stuff */
876ff7e0accSmrg  /* left out colormap */
877ff7e0accSmrg  /* left out map_installed */
878ff7e0accSmrg
879ff7e0accSmrg
880ff7e0accSmrg/*
881ff7e0accSmrg * Display root, parent, and (recursively) children information
882ff7e0accSmrg * recurse - true to show children information
883ff7e0accSmrg */
884ff7e0accSmrgstatic void
885ff7e0accSmrgDisplay_Tree_Info(Window window, int recurse)
886ff7e0accSmrg{
887ff7e0accSmrg    display_tree_info_1(window, recurse, 0);
888ff7e0accSmrg}
889ff7e0accSmrg
890ff7e0accSmrg/*
891ff7e0accSmrg * level - recursion level
892ff7e0accSmrg */
893ff7e0accSmrgstatic void
894ff7e0accSmrgdisplay_tree_info_1(Window window, int recurse, int level)
895ff7e0accSmrg{
896ff7e0accSmrg  int i, j;
897ff7e0accSmrg  int rel_x, rel_y, abs_x, abs_y;
898ff7e0accSmrg  unsigned int width, height, border, depth;
899ff7e0accSmrg  Window root_win, parent_win;
900ff7e0accSmrg  unsigned int num_children;
901ff7e0accSmrg  Window *child_list;
902ff7e0accSmrg  XClassHint classhint;
903ff7e0accSmrg
904ff7e0accSmrg  if (!XQueryTree(dpy, window, &root_win, &parent_win, &child_list,
905ff7e0accSmrg		  &num_children))
906ff7e0accSmrg    Fatal_Error("Can't query window tree.");
907ff7e0accSmrg
908ff7e0accSmrg  if (level == 0) {
909ff7e0accSmrg    printf("\n");
910ff7e0accSmrg    printf("  Root window id: ");
911ff7e0accSmrg    Display_Window_Id(root_win, True);
912ff7e0accSmrg    printf("  Parent window id: ");
913ff7e0accSmrg    Display_Window_Id(parent_win, True);
914ff7e0accSmrg  }
915ff7e0accSmrg
916ff7e0accSmrg  if (level == 0  ||  num_children > 0) {
917ff7e0accSmrg    printf("     ");
918ff7e0accSmrg    for (j=0; j<level; j++) printf("   ");
919ff7e0accSmrg    printf("%d child%s%s\n", num_children, num_children == 1 ? "" : "ren",
920ff7e0accSmrg	   num_children ? ":" : ".");
921ff7e0accSmrg  }
922ff7e0accSmrg
923ff7e0accSmrg  for (i = (int)num_children - 1; i >= 0; i--) {
924ff7e0accSmrg    printf("     ");
925ff7e0accSmrg    for (j=0; j<level; j++) printf("   ");
926ff7e0accSmrg    Display_Window_Id(child_list[i], False);
927ff7e0accSmrg    printf(": (");
928ff7e0accSmrg    if(XGetClassHint(dpy, child_list[i], &classhint)) {
929ff7e0accSmrg	if(classhint.res_name) {
930ff7e0accSmrg	    printf("\"%s\" ", classhint.res_name);
931ff7e0accSmrg	    XFree(classhint.res_name);
932ff7e0accSmrg	} else
933ff7e0accSmrg	    printf("(none) ");
934ff7e0accSmrg	if(classhint.res_class) {
935ff7e0accSmrg	    printf("\"%s\") ", classhint.res_class);
936ff7e0accSmrg	    XFree(classhint.res_class);
937ff7e0accSmrg	} else
938ff7e0accSmrg	    printf("(none)) ");
939ff7e0accSmrg    } else
940ff7e0accSmrg	printf(") ");
941ff7e0accSmrg
942ff7e0accSmrg    if (XGetGeometry(dpy, child_list[i], &root_win,
943ff7e0accSmrg		     &rel_x, &rel_y, &width, &height, &border, &depth)) {
944ff7e0accSmrg	Window child;
945ff7e0accSmrg
946ff7e0accSmrg	printf (" %ux%u+%d+%d", width, height, rel_x, rel_y);
947ff7e0accSmrg	if (XTranslateCoordinates (dpy, child_list[i], root_win,
948ff7e0accSmrg				   0 ,0, &abs_x, &abs_y, &child)) {
949ff7e0accSmrg	    printf ("  +%d+%d", abs_x - border, abs_y - border);
950ff7e0accSmrg	}
951ff7e0accSmrg    }
952ff7e0accSmrg    printf("\n");
953ff7e0accSmrg
954ff7e0accSmrg    if (recurse)
955ff7e0accSmrg	display_tree_info_1(child_list[i], 1, level+1);
956ff7e0accSmrg  }
957ff7e0accSmrg
958ff7e0accSmrg  if (child_list) XFree((char *)child_list);
959ff7e0accSmrg}
960ff7e0accSmrg
961ff7e0accSmrg
962ff7e0accSmrg/*
963ff7e0accSmrg * Display a set of size hints
964ff7e0accSmrg */
965ff7e0accSmrgstatic void
966ff7e0accSmrgDisplay_Hints(XSizeHints *hints)
967ff7e0accSmrg{
968ff7e0accSmrg	long flags;
969ff7e0accSmrg
970ff7e0accSmrg	flags = hints->flags;
971ff7e0accSmrg
972ff7e0accSmrg	if (flags & USPosition)
973ff7e0accSmrg	  printf("      User supplied location: %s, %s\n",
974ff7e0accSmrg		 xscale(hints->x), yscale(hints->y));
975ff7e0accSmrg
976ff7e0accSmrg	if (flags & PPosition)
977ff7e0accSmrg	  printf("      Program supplied location: %s, %s\n",
978ff7e0accSmrg		 xscale(hints->x), yscale(hints->y));
979ff7e0accSmrg
980ff7e0accSmrg	if (flags & USSize) {
981ff7e0accSmrg	  printf("      User supplied size: %s by %s\n",
982ff7e0accSmrg		 xscale(hints->width), yscale(hints->height));
983ff7e0accSmrg	}
984ff7e0accSmrg
985ff7e0accSmrg	if (flags & PSize)
986ff7e0accSmrg	  printf("      Program supplied size: %s by %s\n",
987ff7e0accSmrg		 xscale(hints->width), yscale(hints->height));
988ff7e0accSmrg
989ff7e0accSmrg	if (flags & PMinSize)
990ff7e0accSmrg	  printf("      Program supplied minimum size: %s by %s\n",
991ff7e0accSmrg		 xscale(hints->min_width), yscale(hints->min_height));
992ff7e0accSmrg
993ff7e0accSmrg	if (flags & PMaxSize)
994ff7e0accSmrg	  printf("      Program supplied maximum size: %s by %s\n",
995ff7e0accSmrg		 xscale(hints->max_width), yscale(hints->max_height));
996ff7e0accSmrg
997ff7e0accSmrg	if (flags & PBaseSize) {
998ff7e0accSmrg	  printf("      Program supplied base size: %s by %s\n",
999ff7e0accSmrg		 xscale(hints->base_width), yscale(hints->base_height));
1000ff7e0accSmrg	}
1001ff7e0accSmrg
1002ff7e0accSmrg	if (flags & PResizeInc) {
1003ff7e0accSmrg	  printf("      Program supplied x resize increment: %s\n",
1004ff7e0accSmrg		 xscale(hints->width_inc));
1005ff7e0accSmrg	  printf("      Program supplied y resize increment: %s\n",
1006ff7e0accSmrg		 yscale(hints->height_inc));
1007ff7e0accSmrg	  if (hints->width_inc != 0 && hints->height_inc != 0) {
1008ff7e0accSmrg	      if (flags & USSize)
1009ff7e0accSmrg		  printf("      User supplied size in resize increments:  %s by %s\n",
1010ff7e0accSmrg			 (xscale(hints->width / hints->width_inc)),
1011ff7e0accSmrg			 (yscale(hints->height / hints->height_inc)));
1012ff7e0accSmrg	      if (flags & PSize)
1013ff7e0accSmrg		  printf("      Program supplied size in resize increments:  %s by %s\n",
1014ff7e0accSmrg			 (xscale(hints->width / hints->width_inc)),
1015ff7e0accSmrg			 (yscale(hints->height / hints->height_inc)));
1016ff7e0accSmrg	      if (flags & PMinSize)
1017ff7e0accSmrg		  printf("      Program supplied minimum size in resize increments: %s by %s\n",
1018ff7e0accSmrg			 xscale(hints->min_width / hints->width_inc), yscale(hints->min_height / hints->height_inc));
1019ff7e0accSmrg	      if (flags & PBaseSize)
1020ff7e0accSmrg		  printf("      Program supplied base size in resize increments:  %s by %s\n",
1021ff7e0accSmrg			 (xscale(hints->base_width / hints->width_inc)),
1022ff7e0accSmrg			 (yscale(hints->base_height / hints->height_inc)));
1023ff7e0accSmrg	  }
1024ff7e0accSmrg        }
1025ff7e0accSmrg
1026ff7e0accSmrg	if (flags & PAspect) {
1027ff7e0accSmrg	  printf("      Program supplied min aspect ratio: %s/%s\n",
1028ff7e0accSmrg		 xscale(hints->min_aspect.x), yscale(hints->min_aspect.y));
1029ff7e0accSmrg	  printf("      Program supplied max aspect ratio: %s/%s\n",
1030ff7e0accSmrg		 xscale(hints->max_aspect.x), yscale(hints->max_aspect.y));
1031ff7e0accSmrg        }
1032ff7e0accSmrg
1033ff7e0accSmrg	if (flags & PWinGravity) {
1034ff7e0accSmrg	  printf("      Program supplied window gravity: %s\n",
1035ff7e0accSmrg		 Lookup(hints->win_gravity, _gravities));
1036ff7e0accSmrg	}
1037ff7e0accSmrg}
1038ff7e0accSmrg
1039ff7e0accSmrg
1040ff7e0accSmrg/*
1041ff7e0accSmrg * Display Size Hints info
1042ff7e0accSmrg */
1043ff7e0accSmrgstatic void
1044ff7e0accSmrgDisplay_Size_Hints(Window window)
1045ff7e0accSmrg{
1046ff7e0accSmrg	XSizeHints *hints = XAllocSizeHints();
1047ff7e0accSmrg	long supplied;
1048ff7e0accSmrg
1049ff7e0accSmrg	printf("\n");
1050ff7e0accSmrg	if (!XGetWMNormalHints(dpy, window, hints, &supplied))
1051ff7e0accSmrg	    printf("  No normal window size hints defined\n");
1052ff7e0accSmrg	else {
1053ff7e0accSmrg	    printf("  Normal window size hints:\n");
1054ff7e0accSmrg	    hints->flags &= supplied;
1055ff7e0accSmrg	    Display_Hints(hints);
1056ff7e0accSmrg	}
1057ff7e0accSmrg
1058ff7e0accSmrg	if (!XGetWMSizeHints(dpy, window, hints, &supplied, XA_WM_ZOOM_HINTS))
1059ff7e0accSmrg	    printf("  No zoom window size hints defined\n");
1060ff7e0accSmrg	else {
1061ff7e0accSmrg	    printf("  Zoom window size hints:\n");
1062ff7e0accSmrg	    hints->flags &= supplied;
1063ff7e0accSmrg	    Display_Hints(hints);
1064ff7e0accSmrg	}
1065ff7e0accSmrg	XFree((char *)hints);
1066ff7e0accSmrg}
1067ff7e0accSmrg
1068ff7e0accSmrg
1069ff7e0accSmrgstatic void
1070ff7e0accSmrgDisplay_Window_Shape (Window window)
1071ff7e0accSmrg{
1072ff7e0accSmrg    Bool    ws, bs;
1073ff7e0accSmrg    int	    xws, yws, xbs, ybs;
1074ff7e0accSmrg    unsigned int wws, hws, wbs, hbs;
1075ff7e0accSmrg
1076ff7e0accSmrg    if (!XShapeQueryExtension (dpy, &bs, &ws))
1077ff7e0accSmrg	return;
1078ff7e0accSmrg
1079ff7e0accSmrg    printf("\n");
1080ff7e0accSmrg    XShapeQueryExtents (dpy, window, &ws, &xws, &yws, &wws, &hws,
1081ff7e0accSmrg				     &bs, &xbs, &ybs, &wbs, &hbs);
1082ff7e0accSmrg    if (!ws)
1083ff7e0accSmrg	  printf("  No window shape defined\n");
1084ff7e0accSmrg    else {
1085ff7e0accSmrg	  printf("  Window shape extents:  %sx%s",
1086ff7e0accSmrg		 xscale(wws), yscale(hws));
1087ff7e0accSmrg	  printf("+%s+%s\n", xscale(xws), yscale(yws));
1088ff7e0accSmrg    }
1089ff7e0accSmrg    if (!bs)
1090ff7e0accSmrg	  printf("  No border shape defined\n");
1091ff7e0accSmrg    else {
1092ff7e0accSmrg	  printf("  Border shape extents:  %sx%s",
1093ff7e0accSmrg		 xscale(wbs), yscale(hbs));
1094ff7e0accSmrg	  printf("+%s+%s\n", xscale(xbs), yscale(ybs));
1095ff7e0accSmrg    }
1096ff7e0accSmrg}
1097ff7e0accSmrg
1098ff7e0accSmrg/*
1099ff7e0accSmrg * Display Window Manager Info
1100ff7e0accSmrg */
1101ff7e0accSmrgstatic const binding _state_hints[] = {
1102ff7e0accSmrg	{ DontCareState, "Don't Care State" },
1103ff7e0accSmrg	{ NormalState, "Normal State" },
1104ff7e0accSmrg	{ ZoomState, "Zoomed State" },
1105ff7e0accSmrg	{ IconicState, "Iconic State" },
1106ff7e0accSmrg	{ InactiveState, "Inactive State" },
1107ff7e0accSmrg	{ 0, 0 } };
1108ff7e0accSmrg
1109ff7e0accSmrgstatic void
1110ff7e0accSmrgDisplay_WM_Info(Window window)
1111ff7e0accSmrg{
1112ff7e0accSmrg        XWMHints *wmhints;
1113ff7e0accSmrg	long flags;
1114ff7e0accSmrg
1115ff7e0accSmrg	wmhints = XGetWMHints(dpy, window);
1116ff7e0accSmrg	printf("\n");
1117ff7e0accSmrg	if (!wmhints) {
1118ff7e0accSmrg		printf("  No window manager hints defined\n");
1119ff7e0accSmrg		return;
1120ff7e0accSmrg	}
1121ff7e0accSmrg	flags = wmhints->flags;
1122ff7e0accSmrg
1123ff7e0accSmrg	printf("  Window manager hints:\n");
1124ff7e0accSmrg
1125ff7e0accSmrg	if (flags & InputHint)
1126ff7e0accSmrg	  printf("      Client accepts input or input focus: %s\n",
1127ff7e0accSmrg		 Lookup(wmhints->input, _bool));
1128ff7e0accSmrg
1129ff7e0accSmrg	if (flags & IconWindowHint) {
1130ff7e0accSmrg		printf("      Icon window id: ");
1131ff7e0accSmrg		Display_Window_Id(wmhints->icon_window, True);
1132ff7e0accSmrg	}
1133ff7e0accSmrg
1134ff7e0accSmrg	if (flags & IconPositionHint)
1135ff7e0accSmrg	  printf("      Initial icon position: %s, %s\n",
1136ff7e0accSmrg		 xscale(wmhints->icon_x), yscale(wmhints->icon_y));
1137ff7e0accSmrg
1138ff7e0accSmrg	if (flags & StateHint)
1139ff7e0accSmrg	  printf("      Initial state is %s\n",
1140ff7e0accSmrg		 Lookup(wmhints->initial_state, _state_hints));
1141ff7e0accSmrg
1142ff7e0accSmrg	XFree(wmhints);
1143ff7e0accSmrg}
1144