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