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