aboutsummaryrefslogtreecommitdiff
path: root/apps/xwininfo/xwininfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/xwininfo/xwininfo.c')
-rw-r--r--apps/xwininfo/xwininfo.c1140
1 files changed, 1140 insertions, 0 deletions
diff --git a/apps/xwininfo/xwininfo.c b/apps/xwininfo/xwininfo.c
new file mode 100644
index 000000000..e5d70bcfb
--- /dev/null
+++ b/apps/xwininfo/xwininfo.c
@@ -0,0 +1,1140 @@
+/* $XdotOrg: $ */
+/* $Xorg: xwininfo.c,v 1.4 2001/02/09 02:06:04 xorgcvs Exp $ */
+/*
+
+Copyright 1987, 1998 The Open Group
+Copyright 1999 Sun Microsystems, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+*/
+/* $XFree86: xc/programs/xwininfo/xwininfo.c,v 1.9 2003/09/09 22:08:25 herrb Exp $ */
+
+
+/*
+ * xwininfo.c - MIT Project Athena, X Window system window
+ * information utility.
+ *
+ *
+ * This program will report all relevant information
+ * about a specific window.
+ *
+ * Author: Mark Lillibridge, MIT Project Athena
+ * 16-Jun-87
+ */
+
+#include "config.h"
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Xos.h>
+#include <X11/extensions/shape.h>
+#ifndef NO_I18N
+#include <X11/Xlocale.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Include routines to handle parsing defaults */
+#include "dsimple.h"
+
+typedef struct {
+ long code;
+ const char *name;
+} binding;
+
+static void scale_init(void);
+static char *nscale(int, int, int, char *, size_t);
+static char *xscale(int);
+static char *yscale(int);
+static char *bscale(int);
+static int bad_window_handler(Display *, XErrorEvent *);
+int main(int, char **);
+static const char *LookupL(long, const binding *);
+static const char *Lookup(int, const binding *);
+static void Display_Window_Id(Window, int);
+static void Display_Stats_Info(Window);
+static void Display_Bits_Info(Window);
+static void Display_Event_Mask(long);
+static void Display_Events_Info(Window);
+static void Display_Tree_Info(Window, int);
+static void display_tree_info_1(Window, int, int);
+static void Display_Hints(XSizeHints *);
+static void Display_Size_Hints(Window);
+static void Display_Window_Shape(Window);
+static void Display_WM_Info(Window);
+
+static char *window_id_format = "0x%lx";
+
+#ifndef HAVE_STRLCAT
+static size_t strlcat(char *dst, const char *src, size_t dstsize)
+{
+ size_t sd = strlen(dst);
+ size_t ss = strlen(src);
+ size_t s = sd + ss;
+
+ if (s < dstsize) {
+ strcpy(dst + sd, src);
+ } else {
+ strncpy(dst + sd, src, dstsize-sd-1);
+ dst[dstsize] = '\0';
+ }
+ return s;
+}
+#endif
+
+/*
+ * Report the syntax for calling xwininfo:
+ */
+void
+usage(void)
+{
+ fprintf (stderr,
+ "usage: %s [-options ...]\n\n", program_name);
+ fprintf (stderr,
+ "where options include:\n");
+ fprintf (stderr,
+ " -help print this message\n");
+ fprintf (stderr,
+ " -display host:dpy X server to contact\n");
+ fprintf (stderr,
+ " -root use the root window\n");
+ fprintf (stderr,
+ " -id windowid use the window with the specified id\n");
+ fprintf (stderr,
+ " -name windowname use the window with the specified name\n");
+ fprintf (stderr,
+ " -int print window id in decimal\n");
+ fprintf (stderr,
+ " -children print parent and child identifiers\n");
+ fprintf (stderr,
+ " -tree print children identifiers recursively\n");
+ fprintf (stderr,
+ " -stats print window geometry [DEFAULT]\n");
+ fprintf (stderr,
+ " -bits print window pixel information\n");
+ fprintf (stderr,
+ " -events print events selected for on window\n");
+ fprintf (stderr,
+ " -size print size hints\n");
+ fprintf (stderr,
+ " -wm print window manager hints\n");
+ fprintf (stderr,
+ " -shape print shape extents\n");
+ fprintf (stderr,
+ " -frame don't ignore window manager frames\n");
+ fprintf (stderr,
+ " -english print sizes in english units\n");
+ fprintf (stderr,
+ " -metric print sizes in metric units\n");
+ fprintf (stderr,
+ " -all -tree, -stats, -bits, -events, -wm, -size, -shape\n");
+ fprintf (stderr,
+ "\n");
+ exit (1);
+}
+
+/*
+ * pixel to inch, metric converter.
+ * Hacked in by Mark W. Eichin <eichin@athena> [eichin:19880619.1509EST]
+ *
+ * Simply put: replace the old numbers with string print calls.
+ * Returning a local string is ok, since we only ever get called to
+ * print one x and one y, so as long as they don't collide, they're
+ * fine. This is not meant to be a general purpose routine.
+ *
+ */
+
+#define getdsp(var,fn) var = fn(dpy, DefaultScreen(dpy))
+static int xp=0, xmm=0;
+static int yp=0, ymm=0;
+static int bp=0, bmm=0;
+static int english = 0, metric = 0;
+
+static void
+scale_init(void)
+{
+ getdsp(yp, DisplayHeight);
+ getdsp(ymm, DisplayHeightMM);
+ getdsp(xp, DisplayWidth);
+ getdsp(xmm, DisplayWidthMM);
+ bp = xp + yp;
+ bmm = xmm + ymm;
+}
+
+#define MILE (5280*12)
+#define YARD (3*12)
+#define FOOT (12)
+
+static char *
+nscale(int n, int np, int nmm, char *nbuf, size_t nbufsize)
+{
+ int s;
+ snprintf(nbuf, nbufsize, "%d", n);
+
+ if (metric||english) {
+ s = strlcat(nbuf, " (", nbufsize);
+
+ if (metric) {
+ snprintf(nbuf+s, nbufsize-s, "%.2f mm%s",
+ ((double) n)*nmm/np, english ? "; " : "");
+ }
+ if (english) {
+ double inch_frac;
+ Bool printed_anything = False;
+ int mi, yar, ft, inr;
+
+ inch_frac = ((double) n)*(nmm/25.4)/np;
+ inr = (int)inch_frac;
+ inch_frac -= (double)inr;
+ if (inr >= MILE) {
+ mi = inr/MILE;
+ inr %= MILE;
+ s = strlen(nbuf);
+ snprintf(nbuf+s, nbufsize-s, "%d %s(?!?)",
+ mi, (mi==1) ? "mile" : "miles");
+ printed_anything = True;
+ }
+ if (inr >= YARD) {
+ yar = inr/YARD;
+ inr %= YARD;
+ if (printed_anything)
+ strlcat(nbuf, ", ", nbufsize);
+ s = strlen(nbuf);
+ snprintf(nbuf+s, nbufsize-s, "%d %s",
+ yar, (yar==1) ? "yard" : "yards");
+ printed_anything = True;
+ }
+ if (inr >= FOOT) {
+ ft = inr/FOOT;
+ inr %= FOOT;
+ if (printed_anything)
+ strlcat(nbuf, ", ", nbufsize);
+ s = strlen(nbuf);
+ snprintf(nbuf+s, nbufsize-s, "%d %s",
+ ft, (ft==1) ? "foot" : "feet");
+ printed_anything = True;
+ }
+ if (!printed_anything || inch_frac != 0.0 || inr != 0) {
+ if (printed_anything)
+ strlcat(nbuf, ", ", nbufsize);
+ s = strlen(nbuf);
+ snprintf(nbuf+s, nbufsize-s, "%.2f inches", inr+inch_frac);
+ }
+ }
+ strlcat (nbuf, ")", nbufsize);
+ }
+ return(nbuf);
+}
+
+static char xbuf[BUFSIZ];
+static char *
+xscale(int x)
+{
+ if(!xp) {
+ scale_init();
+ }
+ return(nscale(x, xp, xmm, xbuf, sizeof(xbuf)));
+}
+
+static char ybuf[BUFSIZ];
+static char *
+yscale(int y)
+{
+ if(!yp) {
+ scale_init();
+ }
+ return(nscale(y, yp, ymm, ybuf, sizeof(ybuf)));
+}
+
+static char bbuf[BUFSIZ];
+static char *
+bscale(int b)
+{
+ if(!bp) {
+ scale_init();
+ }
+ return(nscale(b, bp, bmm, bbuf, sizeof(bbuf)));
+}
+
+/* end of pixel to inch, metric converter */
+
+/* This handler is enabled when we are checking
+ to see if the -id the user specified is valid. */
+
+/* ARGSUSED */
+static int
+bad_window_handler(Display *disp, XErrorEvent *err)
+{
+ char badid[20];
+
+ snprintf(badid, sizeof(badid), window_id_format, err->resourceid);
+ Fatal_Error("No such window with id %s.", badid);
+ exit (1);
+ return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ register int i;
+ int tree = 0, stats = 0, bits = 0, events = 0, wm = 0, size = 0, shape = 0;
+ int frame = 0, children = 0;
+ int pauseatend = 0;
+ Window window;
+
+ INIT_NAME;
+
+#ifndef NO_I18N
+ {
+ char *lc;
+ lc = setlocale(LC_ALL, "");
+ if(!lc)
+ fprintf(stderr, "can not set locale properly\n");
+ }
+#endif
+
+ /* Open display, handle command line arguments */
+ Setup_Display_And_Screen(&argc, argv);
+
+ /* Get window selected on command line, if any */
+ window = Select_Window_Args(&argc, argv);
+
+ /* Handle our command line arguments */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-help"))
+ usage();
+ if (!strcmp(argv[i], "-int")) {
+ window_id_format = "%ld";
+ continue;
+ }
+ if (!strcmp(argv[i], "-children")) {
+ children = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-tree")) {
+ tree = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-stats")) {
+ stats = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-bits")) {
+ bits = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-events")) {
+ events = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-wm")) {
+ wm = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-frame")) {
+ frame = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-size")) {
+ size = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-shape")) {
+ shape = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-english")) {
+ english = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-metric")) {
+ metric = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-all")) {
+ tree = stats = bits = events = wm = size = shape = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-pause")) {
+ pauseatend = 1;
+ continue;
+ }
+ usage();
+ }
+
+ /* If no window selected on command line, let user pick one the hard way */
+ if (!window) {
+ printf("\n");
+ printf("xwininfo: Please select the window about which you\n");
+ printf(" would like information by clicking the\n");
+ printf(" mouse in that window.\n");
+ window = Select_Window(dpy, !frame);
+ }
+
+ /*
+ * Do the actual displaying as per parameters
+ */
+ if (!(children || tree || bits || events || wm || size))
+ stats = 1;
+
+ /*
+ * make sure that the window is valid
+ */
+ {
+ Window root;
+ int x, y;
+ unsigned width, height, bw, depth;
+ XErrorHandler old_handler;
+
+ old_handler = XSetErrorHandler(bad_window_handler);
+ XGetGeometry (dpy, window, &root, &x, &y, &width, &height, &bw, &depth);
+ XSync (dpy, False);
+ (void) XSetErrorHandler(old_handler);
+ }
+
+ printf("\nxwininfo: Window id: ");
+ Display_Window_Id(window, True);
+ if (children || tree)
+ Display_Tree_Info(window, tree);
+ if (stats)
+ Display_Stats_Info(window);
+ if (bits)
+ Display_Bits_Info(window);
+ if (events)
+ Display_Events_Info(window);
+ if (wm)
+ Display_WM_Info(window);
+ if (size)
+ Display_Size_Hints(window);
+ if (shape)
+ Display_Window_Shape(window);
+ printf("\n");
+ if (pauseatend) getchar();
+ exit(0);
+}
+
+
+/*
+ * Lookup: lookup a code in a table.
+ */
+static char _lookup_buffer[100];
+
+static const char *
+LookupL(long code, const binding *table)
+{
+ const char *name;
+
+ snprintf(_lookup_buffer, sizeof(_lookup_buffer),
+ "unknown (code = %ld. = 0x%lx)", code, code);
+ name = _lookup_buffer;
+
+ while (table->name) {
+ if (table->code == code) {
+ name = table->name;
+ break;
+ }
+ table++;
+ }
+
+ return(name);
+}
+
+static const char *
+Lookup(int code, const binding *table)
+{
+ return LookupL((long)code, table);
+}
+
+/*
+ * Routine to display a window id in dec/hex with name if window has one
+ */
+
+static void
+Display_Window_Id(Window window, Bool newline_wanted)
+{
+#ifdef NO_I18N
+ char *win_name;
+#else
+ XTextProperty tp;
+#endif
+
+ printf(window_id_format, window); /* print id # in hex/dec */
+
+ if (!window) {
+ printf(" (none)");
+ } else {
+ if (window == RootWindow(dpy, screen)) {
+ printf(" (the root window)");
+ }
+#ifdef NO_I18N
+ if (!XFetchName(dpy, window, &win_name)) { /* Get window name if any */
+ printf(" (has no name)");
+ } else if (win_name) {
+ printf(" \"%s\"", win_name);
+ XFree(win_name);
+ }
+#else
+ if (!XGetWMName(dpy, window, &tp)) { /* Get window name if any */
+ printf(" (has no name)");
+ } else if (tp.nitems > 0) {
+ printf(" \"");
+ {
+ int count = 0, i, ret;
+ char **list = NULL;
+ ret = XmbTextPropertyToTextList(dpy, &tp, &list, &count);
+ if((ret == Success || ret > 0) && list != NULL){
+ for(i=0; i<count; i++)
+ printf("%s", list[i]);
+ XFreeStringList(list);
+ } else {
+ printf("%s", tp.value);
+ }
+ }
+ printf("\"");
+ }
+#endif
+ else
+ printf(" (has no name)");
+ }
+
+ if (newline_wanted)
+ printf("\n");
+
+ return;
+}
+
+
+/*
+ * Display Stats on window
+ */
+static const binding _window_classes[] = {
+ { InputOutput, "InputOutput" },
+ { InputOnly, "InputOnly" },
+ { 0, NULL } };
+
+static const binding _map_states[] = {
+ { IsUnmapped, "IsUnMapped" },
+ { IsUnviewable, "IsUnviewable" },
+ { IsViewable, "IsViewable" },
+ { 0, NULL } };
+
+static const binding _backing_store_states[] = {
+ { NotUseful, "NotUseful" },
+ { WhenMapped, "WhenMapped" },
+ { Always, "Always" },
+ { 0, NULL } };
+
+static const binding _bit_gravity_states[] = {
+ { ForgetGravity, "ForgetGravity" },
+ { NorthWestGravity, "NorthWestGravity" },
+ { NorthGravity, "NorthGravity" },
+ { NorthEastGravity, "NorthEastGravity" },
+ { WestGravity, "WestGravity" },
+ { CenterGravity, "CenterGravity" },
+ { EastGravity, "EastGravity" },
+ { SouthWestGravity, "SouthWestGravity" },
+ { SouthGravity, "SouthGravity" },
+ { SouthEastGravity, "SouthEastGravity" },
+ { StaticGravity, "StaticGravity" },
+ { 0, NULL }};
+
+static const binding _window_gravity_states[] = {
+ { UnmapGravity, "UnmapGravity" },
+ { NorthWestGravity, "NorthWestGravity" },
+ { NorthGravity, "NorthGravity" },
+ { NorthEastGravity, "NorthEastGravity" },
+ { WestGravity, "WestGravity" },
+ { CenterGravity, "CenterGravity" },
+ { EastGravity, "EastGravity" },
+ { SouthWestGravity, "SouthWestGravity" },
+ { SouthGravity, "SouthGravity" },
+ { SouthEastGravity, "SouthEastGravity" },
+ { StaticGravity, "StaticGravity" },
+ { 0, NULL }};
+
+static const binding _visual_classes[] = {
+ { StaticGray, "StaticGray" },
+ { GrayScale, "GrayScale" },
+ { StaticColor, "StaticColor" },
+ { PseudoColor, "PseudoColor" },
+ { TrueColor, "TrueColor" },
+ { DirectColor, "DirectColor" },
+ { 0, NULL }};
+
+static void
+Display_Stats_Info(Window window)
+{
+ XWindowAttributes win_attributes;
+ XVisualInfo vistemplate, *vinfo;
+ XSizeHints hints;
+ int dw = DisplayWidth (dpy, screen), dh = DisplayHeight (dpy, screen);
+ int rx, ry, xright, ybelow;
+ int showright = 0, showbelow = 0;
+ Status status;
+ Window wmframe;
+ int junk;
+ long longjunk;
+ Window junkwin;
+
+ if (!XGetWindowAttributes(dpy, window, &win_attributes))
+ Fatal_Error("Can't get window attributes.");
+ vistemplate.visualid = XVisualIDFromVisual(win_attributes.visual);
+ vinfo = XGetVisualInfo(dpy, VisualIDMask, &vistemplate, &junk);
+
+ (void) XTranslateCoordinates (dpy, window, win_attributes.root,
+ -win_attributes.border_width,
+ -win_attributes.border_width,
+ &rx, &ry, &junkwin);
+
+ xright = (dw - rx - win_attributes.border_width * 2 -
+ win_attributes.width);
+ ybelow = (dh - ry - win_attributes.border_width * 2 -
+ win_attributes.height);
+
+ printf("\n");
+ printf(" Absolute upper-left X: %s\n", xscale(rx));
+ printf(" Absolute upper-left Y: %s\n", yscale(ry));
+ printf(" Relative upper-left X: %s\n", xscale(win_attributes.x));
+ printf(" Relative upper-left Y: %s\n", yscale(win_attributes.y));
+ printf(" Width: %s\n", xscale(win_attributes.width));
+ printf(" Height: %s\n", yscale(win_attributes.height));
+ printf(" Depth: %d\n", win_attributes.depth);
+ printf(" Visual: 0x%lx\n", vinfo->visualid);
+ printf(" Visual Class: %s\n", Lookup(vinfo->class, _visual_classes));
+ printf(" Border width: %s\n", bscale(win_attributes.border_width));
+ printf(" Class: %s\n",
+ Lookup(win_attributes.class, _window_classes));
+ printf(" Colormap: 0x%lx (%sinstalled)\n",
+ win_attributes.colormap, win_attributes.map_installed ? "" : "not ");
+ printf(" Bit Gravity State: %s\n",
+ Lookup(win_attributes.bit_gravity, _bit_gravity_states));
+ printf(" Window Gravity State: %s\n",
+ Lookup(win_attributes.win_gravity, _window_gravity_states));
+ printf(" Backing Store State: %s\n",
+ Lookup(win_attributes.backing_store, _backing_store_states));
+ printf(" Save Under State: %s\n",
+ win_attributes.save_under ? "yes" : "no");
+ printf(" Map State: %s\n",
+ Lookup(win_attributes.map_state, _map_states));
+ printf(" Override Redirect State: %s\n",
+ win_attributes.override_redirect ? "yes" : "no");
+ printf(" Corners: +%d+%d -%d+%d -%d-%d +%d-%d\n",
+ rx, ry, xright, ry, xright, ybelow, rx, ybelow);
+
+ XFree(vinfo);
+
+ /*
+ * compute geometry string that would recreate window
+ */
+ printf(" -geometry ");
+
+ /* compute size in appropriate units */
+ status = XGetWMNormalHints(dpy, window, &hints, &longjunk);
+ if (status && hints.flags & PResizeInc &&
+ hints.width_inc != 0 && hints.height_inc != 0) {
+ if (hints.flags & (PBaseSize|PMinSize)) {
+ if (hints.flags & PBaseSize) {
+ win_attributes.width -= hints.base_width;
+ win_attributes.height -= hints.base_height;
+ } else {
+ /* ICCCM says MinSize is default for BaseSize */
+ win_attributes.width -= hints.min_width;
+ win_attributes.height -= hints.min_height;
+ }
+ }
+ printf("%dx%d", win_attributes.width/hints.width_inc,
+ win_attributes.height/hints.height_inc);
+ } else
+ printf("%dx%d", win_attributes.width, win_attributes.height);
+
+ if (!(hints.flags&PWinGravity))
+ hints.win_gravity = NorthWestGravity; /* per ICCCM */
+ /* find our window manager frame, if any */
+ wmframe = window;
+ while (True) {
+ Window root, parent;
+ Window *childlist;
+ unsigned int ujunk;
+
+ status = XQueryTree(dpy, wmframe, &root, &parent, &childlist, &ujunk);
+ if (parent == root || !parent || !status)
+ break;
+ wmframe = parent;
+ if (status && childlist)
+ XFree((char *)childlist);
+ }
+ if (wmframe != window) {
+ /* WM reparented, so find edges of the frame */
+ /* Only works for ICCCM-compliant WMs, and then only if the
+ window has corner gravity. We would need to know the original width
+ of the window to correctly handle the other gravities. */
+
+ XWindowAttributes frame_attr;
+
+ if (!XGetWindowAttributes(dpy, wmframe, &frame_attr))
+ Fatal_Error("Can't get frame attributes.");
+ switch (hints.win_gravity) {
+ case NorthWestGravity: case SouthWestGravity:
+ case NorthEastGravity: case SouthEastGravity:
+ case WestGravity:
+ rx = frame_attr.x;
+ }
+ switch (hints.win_gravity) {
+ case NorthWestGravity: case SouthWestGravity:
+ case NorthEastGravity: case SouthEastGravity:
+ case EastGravity:
+ xright = dw - frame_attr.x - frame_attr.width -
+ 2*frame_attr.border_width;
+ }
+ switch (hints.win_gravity) {
+ case NorthWestGravity: case SouthWestGravity:
+ case NorthEastGravity: case SouthEastGravity:
+ case NorthGravity:
+ ry = frame_attr.y;
+ }
+ switch (hints.win_gravity) {
+ case NorthWestGravity: case SouthWestGravity:
+ case NorthEastGravity: case SouthEastGravity:
+ case SouthGravity:
+ ybelow = dh - frame_attr.y - frame_attr.height -
+ 2*frame_attr.border_width;
+ }
+ }
+ /* If edge gravity, offer a corner on that edge (because the application
+ programmer cares about that edge), otherwise offer upper left unless
+ some other corner is close to an edge of the screen.
+ (For corner gravity, assume gravity was set by XWMGeometry.
+ For CenterGravity, it doesn't matter.) */
+ if (hints.win_gravity == EastGravity ||
+ (abs(xright) <= 100 && abs(xright) < abs(rx)
+ && hints.win_gravity != WestGravity))
+ showright = 1;
+ if (hints.win_gravity == SouthGravity ||
+ (abs(ybelow) <= 100 && abs(ybelow) < abs(ry)
+ && hints.win_gravity != NorthGravity))
+ showbelow = 1;
+
+ if (showright)
+ printf("-%d", xright);
+ else
+ printf("+%d", rx);
+ if (showbelow)
+ printf("-%d", ybelow);
+ else
+ printf("+%d", ry);
+ printf("\n");
+}
+
+
+/*
+ * Display bits info:
+ */
+static const binding _gravities[] = {
+ { UnmapGravity, "UnMapGravity" }, /* WARNING: both of these have*/
+ { ForgetGravity, "ForgetGravity" }, /* the same value - see code */
+ { NorthWestGravity, "NorthWestGravity" },
+ { NorthGravity, "NorthGravity" },
+ { NorthEastGravity, "NorthEastGravity" },
+ { WestGravity, "WestGravity" },
+ { CenterGravity, "CenterGravity" },
+ { EastGravity, "EastGravity" },
+ { SouthWestGravity, "SouthWestGravity" },
+ { SouthGravity, "SouthGravity" },
+ { SouthEastGravity, "SouthEastGravity" },
+ { StaticGravity, "StaticGravity" },
+ { 0, NULL } };
+
+static const binding _backing_store_hint[] = {
+ { NotUseful, "NotUseful" },
+ { WhenMapped, "WhenMapped" },
+ { Always, "Always" },
+ { 0, NULL } };
+
+static const binding _bool[] = {
+ { 0, "No" },
+ { 1, "Yes" },
+ { 0, NULL } };
+
+static void
+Display_Bits_Info(Window window)
+{
+ XWindowAttributes win_attributes;
+
+ if (!XGetWindowAttributes(dpy, window, &win_attributes))
+ Fatal_Error("Can't get window attributes.");
+
+ printf("\n");
+ printf(" Bit gravity: %s\n",
+ Lookup(win_attributes.bit_gravity, _gravities+1));
+ printf(" Window gravity: %s\n",
+ Lookup(win_attributes.win_gravity, _gravities));
+ printf(" Backing-store hint: %s\n",
+ Lookup(win_attributes.backing_store, _backing_store_hint));
+ printf(" Backing-planes to be preserved: 0x%lx\n",
+ win_attributes.backing_planes);
+ printf(" Backing pixel: %ld\n", win_attributes.backing_pixel);
+ printf(" Save-unders: %s\n",
+ Lookup(win_attributes.save_under, _bool));
+}
+
+
+/*
+ * Routine to display all events in an event mask
+ */
+static const binding _event_mask_names[] = {
+ { KeyPressMask, "KeyPress" },
+ { KeyReleaseMask, "KeyRelease" },
+ { ButtonPressMask, "ButtonPress" },
+ { ButtonReleaseMask, "ButtonRelease" },
+ { EnterWindowMask, "EnterWindow" },
+ { LeaveWindowMask, "LeaveWindow" },
+ { PointerMotionMask, "PointerMotion" },
+ { PointerMotionHintMask, "PointerMotionHint" },
+ { Button1MotionMask, "Button1Motion" },
+ { Button2MotionMask, "Button2Motion" },
+ { Button3MotionMask, "Button3Motion" },
+ { Button4MotionMask, "Button4Motion" },
+ { Button5MotionMask, "Button5Motion" },
+ { ButtonMotionMask, "ButtonMotion" },
+ { KeymapStateMask, "KeymapState" },
+ { ExposureMask, "Exposure" },
+ { VisibilityChangeMask, "VisibilityChange" },
+ { StructureNotifyMask, "StructureNotify" },
+ { ResizeRedirectMask, "ResizeRedirect" },
+ { SubstructureNotifyMask, "SubstructureNotify" },
+ { SubstructureRedirectMask, "SubstructureRedirect" },
+ { FocusChangeMask, "FocusChange" },
+ { PropertyChangeMask, "PropertyChange" },
+ { ColormapChangeMask, "ColormapChange" },
+ { OwnerGrabButtonMask, "OwnerGrabButton" },
+ { 0, NULL } };
+
+static void
+Display_Event_Mask(long mask)
+{
+ long bit, bit_mask;
+
+ for (bit=0, bit_mask=1; bit<sizeof(long)*8; bit++, bit_mask <<= 1)
+ if (mask & bit_mask)
+ printf(" %s\n",
+ LookupL(bit_mask, _event_mask_names));
+}
+
+
+/*
+ * Display info on events
+ */
+static void
+Display_Events_Info(Window window)
+{
+ XWindowAttributes win_attributes;
+
+ if (!XGetWindowAttributes(dpy, window, &win_attributes))
+ Fatal_Error("Can't get window attributes.");
+
+ printf("\n");
+ printf(" Someone wants these events:\n");
+ Display_Event_Mask(win_attributes.all_event_masks);
+
+ printf(" Do not propagate these events:\n");
+ Display_Event_Mask(win_attributes.do_not_propagate_mask);
+
+ printf(" Override redirection?: %s\n",
+ Lookup(win_attributes.override_redirect, _bool));
+}
+
+
+ /* left out visual stuff */
+ /* left out colormap */
+ /* left out map_installed */
+
+
+/*
+ * Display root, parent, and (recursively) children information
+ * recurse - true to show children information
+ */
+static void
+Display_Tree_Info(Window window, int recurse)
+{
+ display_tree_info_1(window, recurse, 0);
+}
+
+/*
+ * level - recursion level
+ */
+static void
+display_tree_info_1(Window window, int recurse, int level)
+{
+ int i, j;
+ int rel_x, rel_y, abs_x, abs_y;
+ unsigned int width, height, border, depth;
+ Window root_win, parent_win;
+ unsigned int num_children;
+ Window *child_list;
+ XClassHint classhint;
+
+ if (!XQueryTree(dpy, window, &root_win, &parent_win, &child_list,
+ &num_children))
+ Fatal_Error("Can't query window tree.");
+
+ if (level == 0) {
+ printf("\n");
+ printf(" Root window id: ");
+ Display_Window_Id(root_win, True);
+ printf(" Parent window id: ");
+ Display_Window_Id(parent_win, True);
+ }
+
+ if (level == 0 || num_children > 0) {
+ printf(" ");
+ for (j=0; j<level; j++) printf(" ");
+ printf("%d child%s%s\n", num_children, num_children == 1 ? "" : "ren",
+ num_children ? ":" : ".");
+ }
+
+ for (i = (int)num_children - 1; i >= 0; i--) {
+ printf(" ");
+ for (j=0; j<level; j++) printf(" ");
+ Display_Window_Id(child_list[i], False);
+ printf(": (");
+ if(XGetClassHint(dpy, child_list[i], &classhint)) {
+ if(classhint.res_name) {
+ printf("\"%s\" ", classhint.res_name);
+ XFree(classhint.res_name);
+ } else
+ printf("(none) ");
+ if(classhint.res_class) {
+ printf("\"%s\") ", classhint.res_class);
+ XFree(classhint.res_class);
+ } else
+ printf("(none)) ");
+ } else
+ printf(") ");
+
+ if (XGetGeometry(dpy, child_list[i], &root_win,
+ &rel_x, &rel_y, &width, &height, &border, &depth)) {
+ Window child;
+
+ printf (" %ux%u+%d+%d", width, height, rel_x, rel_y);
+ if (XTranslateCoordinates (dpy, child_list[i], root_win,
+ 0 ,0, &abs_x, &abs_y, &child)) {
+ printf (" +%d+%d", abs_x - border, abs_y - border);
+ }
+ }
+ printf("\n");
+
+ if (recurse)
+ display_tree_info_1(child_list[i], 1, level+1);
+ }
+
+ if (child_list) XFree((char *)child_list);
+}
+
+
+/*
+ * Display a set of size hints
+ */
+static void
+Display_Hints(XSizeHints *hints)
+{
+ long flags;
+
+ flags = hints->flags;
+
+ if (flags & USPosition)
+ printf(" User supplied location: %s, %s\n",
+ xscale(hints->x), yscale(hints->y));
+
+ if (flags & PPosition)
+ printf(" Program supplied location: %s, %s\n",
+ xscale(hints->x), yscale(hints->y));
+
+ if (flags & USSize) {
+ printf(" User supplied size: %s by %s\n",
+ xscale(hints->width), yscale(hints->height));
+ }
+
+ if (flags & PSize)
+ printf(" Program supplied size: %s by %s\n",
+ xscale(hints->width), yscale(hints->height));
+
+ if (flags & PMinSize)
+ printf(" Program supplied minimum size: %s by %s\n",
+ xscale(hints->min_width), yscale(hints->min_height));
+
+ if (flags & PMaxSize)
+ printf(" Program supplied maximum size: %s by %s\n",
+ xscale(hints->max_width), yscale(hints->max_height));
+
+ if (flags & PBaseSize) {
+ printf(" Program supplied base size: %s by %s\n",
+ xscale(hints->base_width), yscale(hints->base_height));
+ }
+
+ if (flags & PResizeInc) {
+ printf(" Program supplied x resize increment: %s\n",
+ xscale(hints->width_inc));
+ printf(" Program supplied y resize increment: %s\n",
+ yscale(hints->height_inc));
+ if (hints->width_inc != 0 && hints->height_inc != 0) {
+ if (flags & USSize)
+ printf(" User supplied size in resize increments: %s by %s\n",
+ (xscale(hints->width / hints->width_inc)),
+ (yscale(hints->height / hints->height_inc)));
+ if (flags & PSize)
+ printf(" Program supplied size in resize increments: %s by %s\n",
+ (xscale(hints->width / hints->width_inc)),
+ (yscale(hints->height / hints->height_inc)));
+ if (flags & PMinSize)
+ printf(" Program supplied minimum size in resize increments: %s by %s\n",
+ xscale(hints->min_width / hints->width_inc), yscale(hints->min_height / hints->height_inc));
+ if (flags & PBaseSize)
+ printf(" Program supplied base size in resize increments: %s by %s\n",
+ (xscale(hints->base_width / hints->width_inc)),
+ (yscale(hints->base_height / hints->height_inc)));
+ }
+ }
+
+ if (flags & PAspect) {
+ printf(" Program supplied min aspect ratio: %s/%s\n",
+ xscale(hints->min_aspect.x), yscale(hints->min_aspect.y));
+ printf(" Program supplied max aspect ratio: %s/%s\n",
+ xscale(hints->max_aspect.x), yscale(hints->max_aspect.y));
+ }
+
+ if (flags & PWinGravity) {
+ printf(" Program supplied window gravity: %s\n",
+ Lookup(hints->win_gravity, _gravities));
+ }
+}
+
+
+/*
+ * Display Size Hints info
+ */
+static void
+Display_Size_Hints(Window window)
+{
+ XSizeHints *hints = XAllocSizeHints();
+ long supplied;
+
+ printf("\n");
+ if (!XGetWMNormalHints(dpy, window, hints, &supplied))
+ printf(" No normal window size hints defined\n");
+ else {
+ printf(" Normal window size hints:\n");
+ hints->flags &= supplied;
+ Display_Hints(hints);
+ }
+
+ if (!XGetWMSizeHints(dpy, window, hints, &supplied, XA_WM_ZOOM_HINTS))
+ printf(" No zoom window size hints defined\n");
+ else {
+ printf(" Zoom window size hints:\n");
+ hints->flags &= supplied;
+ Display_Hints(hints);
+ }
+ XFree((char *)hints);
+}
+
+
+static void
+Display_Window_Shape (Window window)
+{
+ Bool ws, bs;
+ int xws, yws, xbs, ybs;
+ unsigned int wws, hws, wbs, hbs;
+
+ if (!XShapeQueryExtension (dpy, &bs, &ws))
+ return;
+
+ printf("\n");
+ XShapeQueryExtents (dpy, window, &ws, &xws, &yws, &wws, &hws,
+ &bs, &xbs, &ybs, &wbs, &hbs);
+ if (!ws)
+ printf(" No window shape defined\n");
+ else {
+ printf(" Window shape extents: %sx%s",
+ xscale(wws), yscale(hws));
+ printf("+%s+%s\n", xscale(xws), yscale(yws));
+ }
+ if (!bs)
+ printf(" No border shape defined\n");
+ else {
+ printf(" Border shape extents: %sx%s",
+ xscale(wbs), yscale(hbs));
+ printf("+%s+%s\n", xscale(xbs), yscale(ybs));
+ }
+}
+
+/*
+ * Display Window Manager Info
+ */
+static const binding _state_hints[] = {
+ { DontCareState, "Don't Care State" },
+ { NormalState, "Normal State" },
+ { ZoomState, "Zoomed State" },
+ { IconicState, "Iconic State" },
+ { InactiveState, "Inactive State" },
+ { 0, NULL } };
+
+static void
+Display_WM_Info(Window window)
+{
+ XWMHints *wmhints;
+ long flags;
+
+ wmhints = XGetWMHints(dpy, window);
+ printf("\n");
+ if (!wmhints) {
+ printf(" No window manager hints defined\n");
+ return;
+ }
+ flags = wmhints->flags;
+
+ printf(" Window manager hints:\n");
+
+ if (flags & InputHint)
+ printf(" Client accepts input or input focus: %s\n",
+ Lookup(wmhints->input, _bool));
+
+ if (flags & IconWindowHint) {
+ printf(" Icon window id: ");
+ Display_Window_Id(wmhints->icon_window, True);
+ }
+
+ if (flags & IconPositionHint)
+ printf(" Initial icon position: %s, %s\n",
+ xscale(wmhints->icon_x), yscale(wmhints->icon_y));
+
+ if (flags & StateHint)
+ printf(" Initial state is %s\n",
+ Lookup(wmhints->initial_state, _state_hints));
+
+ XFree(wmhints);
+}