1 /* 2 * xdpyinfo - print information about X display connection 3 * 4 * 5 Copyright 1988, 1998 The Open Group 6 Copyright 2005 Hitachi, Ltd. 7 8 Permission to use, copy, modify, distribute, and sell this software and its 9 documentation for any purpose is hereby granted without fee, provided that 10 the above copyright notice appear in all copies and that both that 11 copyright notice and this permission notice appear in supporting 12 documentation. 13 14 The above copyright notice and this permission notice shall be included in 15 all copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24 Except as contained in this notice, the name of The Open Group shall not be 25 used in advertising or otherwise to promote the sale, use or other dealings 26 in this Software without prior written authorization from The Open Group. 27 * 28 * Author: Jim Fulton, MIT X Consortium 29 */ 30 31 #ifdef HAVE_CONFIG_H 32 # include "config.h" 33 # if HAVE_X11_EXTENSIONS_MULTIBUF_H 34 # define MULTIBUFFER 35 # endif 36 37 # if HAVE_X11_EXTENSIONS_XSHM_H 38 # define MITSHM 39 # endif 40 41 # if HAVE_X11_EXTENSIONS_XKB_H && HAVE_X11_XKBLIB_H 42 # define XKB 43 # endif 44 45 # if HAVE_X11_EXTENSIONS_XF86VMODE_H && \ 46 (HAVE_X11_EXTENSIONS_XF86VMSTR_H || HAVE_X11_EXTENSIONS_XF86VMPROTO_H) 47 # define XF86VIDMODE 48 # endif 49 50 # if (HAVE_X11_EXTENSIONS_XXF86DGA_H && HAVE_X11_EXTENSIONS_XF86DGAPROTO_H) \ 51 || (HAVE_X11_EXTENSIONS_XF86DGA_H && HAVE_X11_EXTENSIONS_XF86DGASTR_H) 52 # define XFreeXDGA 53 # endif 54 55 # if HAVE_X11_EXTENSIONS_XF86MISC_H && HAVE_X11_EXTENSIONS_XF86MSCSTR_H 56 # define XF86MISC 57 # endif 58 59 # if HAVE_X11_EXTENSIONS_XINPUT_H 60 # define XINPUT 61 # endif 62 63 # if HAVE_X11_EXTENSIONS_XRENDER_H 64 # define XRENDER 65 # endif 66 67 # if HAVE_X11_EXTENSIONS_XCOMPOSITE_H 68 # define COMPOSITE 69 # endif 70 71 # if HAVE_X11_EXTENSIONS_XINERAMA_H 72 # define PANORAMIX 73 # endif 74 75 # if HAVE_X11_EXTENSIONS_DMXEXT_H 76 # define DMX 77 # endif 78 79 # if HAVE_X11_EXTENSIONS_XPRESENT_H 80 # define PRESENT 81 # endif 82 83 #endif 84 85 #ifdef WIN32 86 #include <X11/Xwindows.h> 87 #endif 88 89 #include <X11/Xlib-xcb.h> 90 #include <X11/Xlib.h> 91 #include <X11/Xutil.h> 92 #ifdef MULTIBUFFER 93 #include <X11/extensions/multibuf.h> 94 #endif 95 #include <X11/extensions/XTest.h> 96 #include <X11/extensions/sync.h> 97 #include <X11/Xproto.h> 98 #include <X11/extensions/Xdbe.h> 99 #include <X11/extensions/record.h> 100 #include <X11/extensions/shape.h> 101 #ifdef MITSHM 102 #include <X11/extensions/XShm.h> 103 #endif 104 #ifdef XKB 105 #include <X11/extensions/XKB.h> 106 #include <X11/XKBlib.h> 107 #endif 108 #ifdef XF86VIDMODE 109 #include <X11/extensions/xf86vmode.h> 110 # if HAVE_X11_EXTENSIONS_XF86VMPROTO_H /* xf86vidmodeproto 2.2.99.1 & later */ 111 # include <X11/extensions/xf86vmproto.h> 112 # else 113 # include <X11/extensions/xf86vmstr.h> 114 # endif 115 #endif 116 #ifdef XFreeXDGA 117 # if HAVE_X11_EXTENSIONS_XXF86DGA_H && HAVE_X11_EXTENSIONS_XF86DGAPROTO_H 118 # include <X11/extensions/Xxf86dga.h> 119 # include <X11/extensions/xf86dgaproto.h> 120 # else 121 # include <X11/extensions/xf86dga.h> 122 # include <X11/extensions/xf86dgastr.h> 123 # endif 124 #endif 125 #ifdef XF86MISC 126 #include <X11/extensions/xf86misc.h> 127 #include <X11/extensions/xf86mscstr.h> 128 #endif 129 #ifdef XINPUT 130 #include <X11/extensions/XInput.h> 131 #endif 132 #ifdef XRENDER 133 #include <X11/extensions/Xrender.h> 134 #endif 135 #ifdef COMPOSITE 136 #include <X11/extensions/Xcomposite.h> 137 #endif 138 #ifdef PANORAMIX 139 #include <X11/extensions/Xinerama.h> 140 #endif 141 #ifdef DMX 142 #include <X11/extensions/dmxext.h> 143 #endif 144 #ifdef PRESENT 145 #include <X11/extensions/Xpresent.h> 146 #include <X11/extensions/Xrandr.h> 147 #endif 148 #include <X11/Xos.h> 149 #include <stdio.h> 150 #include <stdlib.h> 151 152 static char *ProgramName; 153 static Bool queryExtensions = False; 154 155 #if defined(XF86MISC) 156 static int 157 silent_errors(_X_UNUSED Display *dpy, _X_UNUSED XErrorEvent *ev) 158 { 159 return 0; 160 } 161 #endif 162 163 static int print_event_mask(char *buf, int lastcol, int indent, long mask); 164 165 static int StrCmp(const void *a, const void *b) 166 { 167 return strcmp(*(const char * const *)a, *(const char * const *)b); 168 } 169 170 static void 171 print_extension_info(Display *dpy) 172 { 173 int n = 0; 174 char **extlist = XListExtensions (dpy, &n); 175 176 printf ("number of extensions: %d\n", n); 177 178 if (extlist) { 179 qsort(extlist, (size_t)n, sizeof(char *), StrCmp); 180 181 if (!queryExtensions) { 182 for (int i = 0; i < n; i++) { 183 printf (" %s\n", extlist[i]); 184 } 185 } else { 186 xcb_connection_t *xcb_conn = XGetXCBConnection (dpy); 187 xcb_query_extension_cookie_t *qe_cookies; 188 189 qe_cookies = calloc((size_t)n, sizeof(xcb_query_extension_cookie_t)); 190 if (!qe_cookies) { 191 perror ("calloc failed to allocate memory for extensions"); 192 return; 193 } 194 195 /* 196 * Generate all extension queries at once, so they can be 197 * sent to the xserver in a single batch 198 */ 199 for (int i = 0; i < n; i++) { 200 qe_cookies[i] = xcb_query_extension (xcb_conn, 201 (uint16_t)strlen(extlist[i]), 202 extlist[i]); 203 } 204 205 /* 206 * Start processing replies as they come in. 207 * The first call will flush the queue to the server, then 208 * each one will wait, if needed, for its reply. 209 */ 210 for (int i = 0; i < n; i++) { 211 xcb_query_extension_reply_t *rep 212 = xcb_query_extension_reply(xcb_conn, qe_cookies[i], NULL); 213 214 printf (" %s (opcode: %d", extlist[i], rep->major_opcode); 215 if (rep->first_event) 216 printf (", base event: %d", rep->first_event); 217 if (rep->first_error) 218 printf (", base error: %d", rep->first_error); 219 printf (")\n"); 220 221 free (rep); 222 } 223 free (qe_cookies); 224 } 225 /* do not free, Xlib can depend on contents being unaltered */ 226 /* XFreeExtensionList (extlist); */ 227 } 228 } 229 230 static void 231 print_display_info(Display *dpy) 232 { 233 char dummybuf[40]; 234 const char *cp; 235 int minkeycode, maxkeycode; 236 int n; 237 long req_size; 238 XPixmapFormatValues *pmf; 239 Window focuswin; 240 int focusrevert; 241 242 printf ("name of display: %s\n", DisplayString (dpy)); 243 printf ("version number: %d.%d\n", 244 ProtocolVersion (dpy), ProtocolRevision (dpy)); 245 printf ("vendor string: %s\n", ServerVendor (dpy)); 246 printf ("vendor release number: %d\n", VendorRelease (dpy)); 247 248 if (strstr(ServerVendor (dpy), "X.Org")) { 249 int vendrel = VendorRelease(dpy); 250 251 printf("X.Org version: "); 252 if (vendrel >= 12100000) { 253 vendrel -= 10000000; /* Y2.1K compliant */ 254 printf("%d.%d", 255 (vendrel / 100000) % 100, 256 (vendrel / 1000) % 100); 257 } else { 258 printf("%d.%d.%d", vendrel / 10000000, 259 (vendrel / 100000) % 100, 260 (vendrel / 1000) % 100); 261 } 262 if (vendrel % 1000) 263 printf(".%d", vendrel % 1000); 264 printf("\n"); 265 } 266 else if (strstr(ServerVendor (dpy), "XFree86")) { 267 int vendrel = VendorRelease(dpy); 268 269 printf("XFree86 version: "); 270 if (vendrel < 336) { 271 /* 272 * vendrel was set incorrectly for 3.3.4 and 3.3.5, so handle 273 * those cases here. 274 */ 275 printf("%d.%d.%d", vendrel / 100, 276 (vendrel / 10) % 10, 277 vendrel % 10); 278 } else if (vendrel < 3900) { 279 /* 3.3.x versions, other than the exceptions handled above */ 280 printf("%d.%d", vendrel / 1000, 281 (vendrel / 100) % 10); 282 if (((vendrel / 10) % 10) || (vendrel % 10)) { 283 printf(".%d", (vendrel / 10) % 10); 284 if (vendrel % 10) { 285 printf(".%d", vendrel % 10); 286 } 287 } 288 } else if (vendrel < 40000000) { 289 /* 4.0.x versions */ 290 printf("%d.%d", vendrel / 1000, 291 (vendrel / 10) % 10); 292 if (vendrel % 10) { 293 printf(".%d", vendrel % 10); 294 } 295 } else { 296 /* post-4.0.x */ 297 printf("%d.%d.%d", vendrel / 10000000, 298 (vendrel / 100000) % 100, 299 (vendrel / 1000) % 100); 300 if (vendrel % 1000) { 301 printf(".%d", vendrel % 1000); 302 } 303 } 304 printf("\n"); 305 } 306 307 if (strstr(ServerVendor (dpy), "DMX")) { 308 int vendrel = VendorRelease(dpy); 309 int major, minor, year, month, day; 310 311 major = vendrel / 100000000; 312 vendrel -= major * 100000000; 313 minor = vendrel / 1000000; 314 vendrel -= minor * 1000000; 315 year = vendrel / 10000; 316 vendrel -= year * 10000; 317 month = vendrel / 100; 318 vendrel -= month * 100; 319 day = vendrel; 320 321 /* Add other epoch tests here */ 322 if (major > 0 && minor > 0) year += 2000; 323 324 /* Do some sanity tests in case there is 325 * another server with the same vendor 326 * string. That server could easily use 327 * values < 100000000, which would have 328 * the effect of keeping our major 329 * number 0. */ 330 if (major > 0 && major <= 20 331 && minor >= 0 && minor <= 99 332 && year >= 2000 333 && month >= 1 && month <= 12 334 && day >= 1 && day <= 31) 335 printf("DMX version: %d.%d.%04d%02d%02d\n", 336 major, minor, year, month, day); 337 } 338 339 req_size = XExtendedMaxRequestSize (dpy); 340 if (!req_size) req_size = XMaxRequestSize (dpy); 341 printf ("maximum request size: %ld bytes\n", req_size * 4); 342 printf ("motion buffer size: %ld\n", XDisplayMotionBufferSize (dpy)); 343 344 switch (BitmapBitOrder (dpy)) { 345 case LSBFirst: cp = "LSBFirst"; break; 346 case MSBFirst: cp = "MSBFirst"; break; 347 default: 348 snprintf (dummybuf, sizeof(dummybuf), 349 "unknown order %d", BitmapBitOrder (dpy)); 350 cp = dummybuf; 351 break; 352 } 353 printf ("bitmap unit, bit order, padding: %d, %s, %d\n", 354 BitmapUnit (dpy), cp, BitmapPad (dpy)); 355 356 switch (ImageByteOrder (dpy)) { 357 case LSBFirst: cp = "LSBFirst"; break; 358 case MSBFirst: cp = "MSBFirst"; break; 359 default: 360 snprintf (dummybuf, sizeof(dummybuf), 361 "unknown order %d", ImageByteOrder (dpy)); 362 cp = dummybuf; 363 break; 364 } 365 printf ("image byte order: %s\n", cp); 366 367 pmf = XListPixmapFormats (dpy, &n); 368 printf ("number of supported pixmap formats: %d\n", n); 369 if (pmf) { 370 printf ("supported pixmap formats:\n"); 371 for (int i = 0; i < n; i++) { 372 printf (" depth %d, bits_per_pixel %d, scanline_pad %d\n", 373 pmf[i].depth, pmf[i].bits_per_pixel, pmf[i].scanline_pad); 374 } 375 XFree ((char *) pmf); 376 } 377 378 379 /* 380 * when we get interfaces to the PixmapFormat stuff, insert code here 381 */ 382 383 XDisplayKeycodes (dpy, &minkeycode, &maxkeycode); 384 printf ("keycode range: minimum %d, maximum %d\n", 385 minkeycode, maxkeycode); 386 387 XGetInputFocus (dpy, &focuswin, &focusrevert); 388 printf ("focus: "); 389 switch (focuswin) { 390 case PointerRoot: 391 printf ("PointerRoot\n"); 392 break; 393 case None: 394 printf ("None\n"); 395 break; 396 default: 397 printf("window 0x%lx, revert to ", focuswin); 398 switch (focusrevert) { 399 case RevertToParent: 400 printf ("Parent\n"); 401 break; 402 case RevertToNone: 403 printf ("None\n"); 404 break; 405 case RevertToPointerRoot: 406 printf ("PointerRoot\n"); 407 break; 408 default: /* should not happen */ 409 printf ("%d\n", focusrevert); 410 break; 411 } 412 break; 413 } 414 415 print_extension_info (dpy); 416 417 printf ("default screen number: %d\n", DefaultScreen (dpy)); 418 printf ("number of screens: %d\n", ScreenCount (dpy)); 419 } 420 421 static void 422 print_visual_info(XVisualInfo *vip) 423 { 424 char errorbuf[40]; /* for sprintfing into */ 425 const char *class = NULL; /* for printing */ 426 427 switch (vip->class) { 428 case StaticGray: class = "StaticGray"; break; 429 case GrayScale: class = "GrayScale"; break; 430 case StaticColor: class = "StaticColor"; break; 431 case PseudoColor: class = "PseudoColor"; break; 432 case TrueColor: class = "TrueColor"; break; 433 case DirectColor: class = "DirectColor"; break; 434 default: 435 snprintf (errorbuf, sizeof(errorbuf), "unknown class %d", vip->class); 436 class = errorbuf; 437 break; 438 } 439 440 printf (" visual:\n"); 441 printf (" visual id: 0x%lx\n", vip->visualid); 442 printf (" class: %s\n", class); 443 printf (" depth: %d plane%s\n", vip->depth, 444 vip->depth == 1 ? "" : "s"); 445 if (vip->class == TrueColor || vip->class == DirectColor) 446 printf (" available colormap entries: %d per subfield\n", 447 vip->colormap_size); 448 else 449 printf (" available colormap entries: %d\n", 450 vip->colormap_size); 451 printf (" red, green, blue masks: 0x%lx, 0x%lx, 0x%lx\n", 452 vip->red_mask, vip->green_mask, vip->blue_mask); 453 printf (" significant bits in color specification: %d bits\n", 454 vip->bits_per_rgb); 455 } 456 457 static void 458 print_screen_info(Display *dpy, int scr) 459 { 460 Screen *s = ScreenOfDisplay (dpy, scr); /* opaque structure */ 461 XVisualInfo viproto; /* fill in for getting info */ 462 XVisualInfo *vip; /* returned info */ 463 int nvi; /* number of elements returned */ 464 char eventbuf[80]; /* want 79 chars per line + nul */ 465 static const char *yes = "YES", *no = "NO", *when = "WHEN MAPPED"; 466 double xres, yres; 467 int ndepths = 0, *depths = NULL; 468 unsigned int width, height; 469 470 /* 471 * there are 2.54 centimeters to an inch; so there are 25.4 millimeters. 472 * 473 * dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch)) 474 * = N pixels / (M inch / 25.4) 475 * = N * 25.4 pixels / M inch 476 */ 477 478 xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) / 479 ((double) DisplayWidthMM(dpy,scr))); 480 yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) / 481 ((double) DisplayHeightMM(dpy,scr))); 482 483 printf ("\n"); 484 printf ("screen #%d:\n", scr); 485 printf (" dimensions: %dx%d pixels (%dx%d millimeters)\n", 486 XDisplayWidth (dpy, scr), XDisplayHeight (dpy, scr), 487 XDisplayWidthMM(dpy, scr), XDisplayHeightMM (dpy, scr)); 488 printf (" resolution: %dx%d dots per inch\n", 489 (int) (xres + 0.5), (int) (yres + 0.5)); 490 depths = XListDepths (dpy, scr, &ndepths); 491 if (!depths) ndepths = 0; 492 printf (" depths (%d): ", ndepths); 493 for (int i = 0; i < ndepths; i++) { 494 printf ("%d", depths[i]); 495 if (i < ndepths - 1) { 496 putchar (','); 497 putchar (' '); 498 } 499 } 500 putchar ('\n'); 501 if (depths) XFree ((char *) depths); 502 printf (" root window id: 0x%lx\n", RootWindow (dpy, scr)); 503 printf (" depth of root window: %d plane%s\n", 504 DisplayPlanes (dpy, scr), 505 DisplayPlanes (dpy, scr) == 1 ? "" : "s"); 506 printf (" number of colormaps: minimum %d, maximum %d\n", 507 MinCmapsOfScreen(s), MaxCmapsOfScreen(s)); 508 printf (" default colormap: 0x%lx\n", DefaultColormap (dpy, scr)); 509 printf (" default number of colormap cells: %d\n", 510 DisplayCells (dpy, scr)); 511 printf (" preallocated pixels: black %ld, white %ld\n", 512 BlackPixel (dpy, scr), WhitePixel (dpy, scr)); 513 printf (" options: backing-store %s, save-unders %s\n", 514 (DoesBackingStore (s) == NotUseful) ? no : 515 ((DoesBackingStore (s) == Always) ? yes : when), 516 DoesSaveUnders (s) ? yes : no); 517 XQueryBestSize (dpy, CursorShape, RootWindow (dpy, scr), 65535, 65535, 518 &width, &height); 519 if (width == 65535 && height == 65535) 520 printf (" largest cursor: unlimited\n"); 521 else 522 printf (" largest cursor: %dx%d\n", width, height); 523 printf (" current input event mask: 0x%lx\n", EventMaskOfScreen (s)); 524 (void) print_event_mask (eventbuf, 79, 4, EventMaskOfScreen (s)); 525 526 nvi = 0; 527 viproto.screen = scr; 528 vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi); 529 printf (" number of visuals: %d\n", nvi); 530 printf (" default visual id: 0x%lx\n", 531 XVisualIDFromVisual (DefaultVisual (dpy, scr))); 532 for (int i = 0; i < nvi; i++) { 533 print_visual_info (vip+i); 534 } 535 if (vip) XFree ((char *) vip); 536 } 537 538 /* 539 * The following routine prints out an event mask, wrapping events at nice 540 * boundaries. 541 */ 542 543 #define MASK_NAME_WIDTH 25 544 545 static struct _event_table { 546 const char *name; 547 long value; 548 } event_table[] = { 549 { "KeyPressMask ", KeyPressMask }, 550 { "KeyReleaseMask ", KeyReleaseMask }, 551 { "ButtonPressMask ", ButtonPressMask }, 552 { "ButtonReleaseMask ", ButtonReleaseMask }, 553 { "EnterWindowMask ", EnterWindowMask }, 554 { "LeaveWindowMask ", LeaveWindowMask }, 555 { "PointerMotionMask ", PointerMotionMask }, 556 { "PointerMotionHintMask ", PointerMotionHintMask }, 557 { "Button1MotionMask ", Button1MotionMask }, 558 { "Button2MotionMask ", Button2MotionMask }, 559 { "Button3MotionMask ", Button3MotionMask }, 560 { "Button4MotionMask ", Button4MotionMask }, 561 { "Button5MotionMask ", Button5MotionMask }, 562 { "ButtonMotionMask ", ButtonMotionMask }, 563 { "KeymapStateMask ", KeymapStateMask }, 564 { "ExposureMask ", ExposureMask }, 565 { "VisibilityChangeMask ", VisibilityChangeMask }, 566 { "StructureNotifyMask ", StructureNotifyMask }, 567 { "ResizeRedirectMask ", ResizeRedirectMask }, 568 { "SubstructureNotifyMask ", SubstructureNotifyMask }, 569 { "SubstructureRedirectMask ", SubstructureRedirectMask }, 570 { "FocusChangeMask ", FocusChangeMask }, 571 { "PropertyChangeMask ", PropertyChangeMask }, 572 { "ColormapChangeMask ", ColormapChangeMask }, 573 { "OwnerGrabButtonMask ", OwnerGrabButtonMask }, 574 { NULL, 0 }}; 575 576 static int 577 print_event_mask(char *buf, /* string to write into */ 578 int lastcol, /* strlen(buf)+1 */ 579 int indent, /* amount by which to indent */ 580 long mask) /* event mask */ 581 { 582 int len; 583 int bitsfound = 0; 584 585 buf[0] = buf[lastcol] = '\0'; /* just in case */ 586 587 #define INDENT() do { len = indent; memset(buf, ' ', indent); } while (0) 588 589 INDENT (); 590 591 for (struct _event_table *etp = event_table; etp->name; etp++) { 592 if (mask & etp->value) { 593 if (len + MASK_NAME_WIDTH > lastcol) { 594 puts (buf); 595 INDENT (); 596 } 597 strcpy (buf+len, etp->name); 598 len += MASK_NAME_WIDTH; 599 bitsfound++; 600 } 601 } 602 603 if (bitsfound) puts (buf); 604 605 #undef INDENT 606 607 return (bitsfound); 608 } 609 610 static void 611 print_standard_extension_info(Display *dpy, const char *extname, 612 int majorrev, int minorrev) 613 { 614 int opcode, event, error; 615 616 printf("%s version %d.%d ", extname, majorrev, minorrev); 617 618 XQueryExtension(dpy, extname, &opcode, &event, &error); 619 printf ("opcode: %d", opcode); 620 if (event) 621 printf (", base event: %d", event); 622 if (error) 623 printf (", base error: %d", error); 624 printf("\n"); 625 } 626 627 #ifdef MULTIBUFFER 628 static int 629 print_multibuf_info(Display *dpy, const char *extname) 630 { 631 #define MULTIBUF_FMT " visual id, max buffers, depth: 0x%lx, %d, %d\n" 632 int majorrev, minorrev; 633 634 if (!XmbufGetVersion(dpy, &majorrev, &minorrev)) 635 return 0; 636 637 print_standard_extension_info(dpy, extname, majorrev, minorrev); 638 639 for (int i = 0; i < ScreenCount (dpy); i++) 640 { 641 int nmono, nstereo; /* count */ 642 XmbufBufferInfo *mono_info = NULL, *stereo_info = NULL; /* arrays */ 643 const int scr = 0; 644 645 if (!XmbufGetScreenInfo (dpy, RootWindow(dpy, scr), &nmono, &mono_info, 646 &nstereo, &stereo_info)) { 647 fprintf (stderr, 648 "%s: unable to get multibuffer info for screen %d\n", 649 ProgramName, scr); 650 } else { 651 printf (" screen %d number of mono multibuffer types: %d\n", i, nmono); 652 for (int j = 0; j < nmono; j++) { 653 printf (MULTIBUF_FMT, mono_info[j].visualid, 654 mono_info[j].max_buffers, mono_info[j].depth); 655 } 656 printf (" number of stereo multibuffer types: %d\n", nstereo); 657 for (int j = 0; j < nstereo; j++) { 658 printf (MULTIBUF_FMT, stereo_info[j].visualid, 659 stereo_info[j].max_buffers, stereo_info[j].depth); 660 } 661 if (mono_info) XFree ((char *) mono_info); 662 if (stereo_info) XFree ((char *) stereo_info); 663 } 664 } 665 return 1; 666 } /* end print_multibuf_info */ 667 #endif 668 669 static int 670 print_xtest_info(Display *dpy, const char *extname) 671 { 672 int majorrev, minorrev, foo; 673 674 if (!XTestQueryExtension(dpy, &foo, &foo, &majorrev, &minorrev)) 675 return 0; 676 print_standard_extension_info(dpy, extname, majorrev, minorrev); 677 return 1; 678 } 679 680 static int 681 print_sync_info(Display *dpy, const char *extname) 682 { 683 int majorrev, minorrev; 684 XSyncSystemCounter *syscounters; 685 int ncounters; 686 687 if (!XSyncInitialize(dpy, &majorrev, &minorrev)) 688 return 0; 689 print_standard_extension_info(dpy, extname, majorrev, minorrev); 690 691 syscounters = XSyncListSystemCounters(dpy, &ncounters); 692 printf(" system counters: %d\n", ncounters); 693 for (int i = 0; i < ncounters; i++) 694 { 695 printf(" %s id: 0x%08x resolution_lo: %d resolution_hi: %d\n", 696 syscounters[i].name, (unsigned int)syscounters[i].counter, 697 XSyncValueLow32(syscounters[i].resolution), 698 XSyncValueHigh32(syscounters[i].resolution)); 699 } 700 XSyncFreeSystemCounterList(syscounters); 701 return 1; 702 } 703 704 static int 705 print_shape_info(Display *dpy, const char *extname) 706 { 707 int majorrev, minorrev; 708 709 if (!XShapeQueryVersion(dpy, &majorrev, &minorrev)) 710 return 0; 711 print_standard_extension_info(dpy, extname, majorrev, minorrev); 712 return 1; 713 } 714 715 #ifdef XFreeXDGA 716 static int 717 catch_dga_errors(Display *dpy, XErrorEvent *event) 718 { 719 char error_name[128]; 720 char request_name[128]; 721 char code[64]; 722 723 XGetErrorText(dpy, event->error_code, error_name, sizeof(error_name)); 724 if (event->request_code < 128) { 725 snprintf(code, sizeof(code), "%d", event->request_code); 726 XGetErrorDatabaseText(dpy, "XRequest", code, "", 727 request_name, sizeof(request_name)); 728 } else { 729 snprintf(code, sizeof(code), "%s.%d", "XFree86-DGA", event->minor_code); 730 XGetErrorDatabaseText(dpy, "XRequest", code, "", 731 request_name, sizeof(request_name)); 732 } 733 734 printf(" DGA: %s returned error: %s\n", request_name, error_name); 735 return 0; 736 } 737 738 static int 739 print_dga_info(Display *dpy, const char *extname) 740 { 741 unsigned int offset; 742 int majorrev, minorrev, width, bank, ram, flags; 743 XErrorHandler old_handler; 744 745 old_handler = XSetErrorHandler(catch_dga_errors); 746 747 if (!XF86DGAQueryVersion(dpy, &majorrev, &minorrev)) 748 return 0; 749 print_standard_extension_info(dpy, extname, majorrev, minorrev); 750 751 if (!XF86DGAQueryDirectVideo(dpy, DefaultScreen(dpy), &flags) 752 || ! (flags & XF86DGADirectPresent) ) 753 { 754 printf(" DGA not available on screen %d.\n", DefaultScreen(dpy)); 755 return 1; 756 } 757 758 if (!XF86DGAGetVideoLL(dpy, DefaultScreen(dpy), &offset, 759 &width, &bank, &ram)) 760 return 0; 761 printf(" Base address = 0x%X, Width = %d, Bank size = %d," 762 " RAM size = %dk\n", offset, width, bank, ram); 763 764 XSetErrorHandler(old_handler); 765 766 return 1; 767 } 768 #endif 769 770 #ifdef XF86VIDMODE 771 #define V_PHSYNC 0x001 772 #define V_NHSYNC 0x002 773 #define V_PVSYNC 0x004 774 #define V_NVSYNC 0x008 775 #define V_INTERLACE 0x010 776 #define V_DBLSCAN 0x020 777 #define V_CSYNC 0x040 778 #define V_PCSYNC 0x080 779 #define V_NCSYNC 0x100 780 781 static void 782 print_XF86VidMode_modeline( 783 unsigned int dotclock, 784 unsigned short hdisplay, 785 unsigned short hsyncstart, 786 unsigned short hsyncend, 787 unsigned short htotal, 788 unsigned short vdisplay, 789 unsigned short vsyncstart, 790 unsigned short vsyncend, 791 unsigned short vtotal, 792 unsigned int flags) 793 { 794 printf(" %6.2f %4d %4d %4d %4d %4d %4d %4d %4d ", 795 dotclock/1000.0, 796 hdisplay, hsyncstart, hsyncend, htotal, 797 vdisplay, vsyncstart, vsyncend, vtotal); 798 if (flags & V_PHSYNC) printf(" +hsync"); 799 if (flags & V_NHSYNC) printf(" -hsync"); 800 if (flags & V_PVSYNC) printf(" +vsync"); 801 if (flags & V_NVSYNC) printf(" -vsync"); 802 if (flags & V_INTERLACE) printf(" interlace"); 803 if (flags & V_CSYNC) printf(" composite"); 804 if (flags & V_PCSYNC) printf(" +csync"); 805 if (flags & V_NCSYNC) printf(" -csync"); 806 if (flags & V_DBLSCAN) printf(" doublescan"); 807 printf("\n"); 808 } 809 810 static int 811 print_XF86VidMode_info(Display *dpy, const char *extname) 812 { 813 int majorrev, minorrev; 814 XF86VidModeMonitor monitor; 815 816 if (!XF86VidModeQueryVersion(dpy, &majorrev, &minorrev)) 817 return 0; 818 print_standard_extension_info(dpy, extname, majorrev, minorrev); 819 820 if (XF86VidModeGetMonitor(dpy, DefaultScreen(dpy), &monitor)) { 821 printf(" Monitor Information:\n"); 822 printf(" Vendor: %s, Model: %s\n", 823 monitor.vendor == NULL ? "" : monitor.vendor, 824 monitor.model == NULL ? "" : monitor.model); 825 printf(" Num hsync: %d, Num vsync: %d\n", 826 monitor.nhsync, monitor.nvsync); 827 for (int i = 0; i < monitor.nhsync; i++) { 828 printf(" hsync range %d: %6.2f - %6.2f\n", i, 829 monitor.hsync[i].lo, monitor.hsync[i].hi); 830 } 831 for (int i = 0; i < monitor.nvsync; i++) { 832 printf(" vsync range %d: %6.2f - %6.2f\n", i, 833 monitor.vsync[i].lo, monitor.vsync[i].hi); 834 } 835 XFree(monitor.vendor); 836 XFree(monitor.model); 837 XFree(monitor.hsync); 838 XFree(monitor.vsync); 839 } else { 840 printf(" Monitor Information not available\n"); 841 } 842 843 if ((majorrev > 0) || (majorrev == 0 && minorrev > 5)) { 844 int modecount, dotclock; 845 XF86VidModeModeLine modeline; 846 XF86VidModeModeInfo **modelines; 847 848 if (XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &modecount, 849 &modelines)) { 850 printf(" Available Video Mode Settings:\n"); 851 printf(" Clock Hdsp Hbeg Hend Httl Vdsp Vbeg Vend Vttl Flags\n"); 852 for (int i = 0; i < modecount; i++) { 853 print_XF86VidMode_modeline 854 (modelines[i]->dotclock, modelines[i]->hdisplay, 855 modelines[i]->hsyncstart, modelines[i]->hsyncend, 856 modelines[i]->htotal, modelines[i]->vdisplay, 857 modelines[i]->vsyncstart, modelines[i]->vsyncend, 858 modelines[i]->vtotal, modelines[i]->flags); 859 } 860 XFree(modelines); 861 } else { 862 printf(" Available Video Mode Settings not available\n"); 863 } 864 865 if (XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), 866 &dotclock, &modeline)) { 867 printf(" Current Video Mode Setting:\n"); 868 print_XF86VidMode_modeline(dotclock, 869 modeline.hdisplay, modeline.hsyncstart, 870 modeline.hsyncend, modeline.htotal, 871 modeline.vdisplay, modeline.vsyncstart, 872 modeline.vsyncend, modeline.vtotal, 873 modeline.flags); 874 } else { 875 printf(" Current Video Mode Setting not available\n"); 876 } 877 } 878 879 return 1; 880 } 881 #endif 882 883 #ifdef XF86MISC 884 885 static const char *kbdtable[] = { 886 "Unknown", "84-key", "101-key", "Other", "Xqueue" }; 887 static const char *msetable[] = { 888 "None", "Microsoft", "MouseSystems", "MMSeries", 889 "Logitech", "BusMouse", "Mouseman", "PS/2", "MMHitTab", 890 "GlidePoint", "IntelliMouse", "ThinkingMouse", 891 "IMPS/2", "ThinkingMousePS/2", "MouseManPlusPS/2", 892 "GlidePointPS/2", "NetMousePS/2", "NetScrollPS/2", 893 "SysMouse", "Auto" }; 894 static const char *flgtable[] = { 895 "None", "ClearDTR", "ClearRTS", "ClearDTR and ClearRTS" }; 896 897 static int 898 print_XF86Misc_info(Display *dpy, const char *extname) 899 { 900 int majorrev, minorrev; 901 XErrorHandler old_handler; 902 903 if (!XF86MiscQueryVersion(dpy, &majorrev, &minorrev)) 904 return 0; 905 print_standard_extension_info(dpy, extname, majorrev, minorrev); 906 907 old_handler = XSetErrorHandler(silent_errors); 908 909 if ((majorrev > 0) || (majorrev == 0 && minorrev > 0)) { 910 XF86MiscKbdSettings kbdinfo; 911 XF86MiscMouseSettings mouseinfo; 912 913 if (!XF86MiscGetKbdSettings(dpy, &kbdinfo)) 914 return 0; 915 printf(" Keyboard Settings- Type: %s, Rate: %d, Delay: %d, ServerNumLock: %s\n", 916 kbdtable[kbdinfo.type], kbdinfo.rate, kbdinfo.delay, 917 (kbdinfo.servnumlock? "yes": "no")); 918 919 if (!XF86MiscGetMouseSettings(dpy, &mouseinfo)) 920 return 0; 921 printf(" Mouse Settings- Device: %s, Type: ", 922 strlen(mouseinfo.device) == 0 ? "None": mouseinfo.device); 923 XFree(mouseinfo.device); 924 if (mouseinfo.type == MTYPE_XQUEUE) 925 printf("Xqueue\n"); 926 else if (mouseinfo.type == MTYPE_OSMOUSE) 927 printf("OSMouse\n"); 928 else if (mouseinfo.type <= MTYPE_AUTOMOUSE) 929 printf("%s\n", msetable[mouseinfo.type+1]); 930 else 931 printf("Unknown\n"); 932 printf(" BaudRate: %d, SampleRate: %d, Resolution: %d\n", 933 mouseinfo.baudrate, mouseinfo.samplerate, mouseinfo.resolution); 934 printf(" Emulate3Buttons: %s, Emulate3Timeout: %d ms\n", 935 mouseinfo.emulate3buttons? "yes": "no", mouseinfo.emulate3timeout); 936 printf(" ChordMiddle: %s, Flags: %s\n", 937 mouseinfo.chordmiddle? "yes": "no", 938 flgtable[(mouseinfo.flags & MF_CLEAR_DTR? 1: 0) 939 +(mouseinfo.flags & MF_CLEAR_RTS? 1: 0)] ); 940 printf(" Buttons: %d\n", mouseinfo.buttons); 941 } 942 943 XSetErrorHandler(old_handler); 944 945 return 1; 946 } 947 #endif 948 949 #ifdef MITSHM 950 static int 951 print_mitshm_info(Display *dpy, const char *extname) 952 { 953 int majorrev, minorrev; 954 Bool sharedPixmaps; 955 956 if (!XShmQueryVersion(dpy, &majorrev, &minorrev, &sharedPixmaps)) 957 return 0; 958 print_standard_extension_info(dpy, extname, majorrev, minorrev); 959 printf(" shared pixmaps: "); 960 if (sharedPixmaps) 961 { 962 int format = XShmPixmapFormat(dpy); 963 printf("yes, format: %d\n", format); 964 } 965 else 966 { 967 printf("no\n"); 968 } 969 return 1; 970 } 971 #endif /* MITSHM */ 972 973 #ifdef XKB 974 static int 975 print_xkb_info(Display *dpy, const char *extname) 976 { 977 int opcode, eventbase, errorbase, majorrev, minorrev; 978 979 if (!XkbQueryExtension(dpy, &opcode, &eventbase, &errorbase, 980 &majorrev, &minorrev)) { 981 return 0; 982 } 983 printf("%s version %d.%d ", extname, majorrev, minorrev); 984 985 printf ("opcode: %d", opcode); 986 if (eventbase) 987 printf (", base event: %d", eventbase); 988 if (errorbase) 989 printf (", base error: %d", errorbase); 990 printf("\n"); 991 992 return 1; 993 } 994 #endif 995 996 static int 997 print_dbe_info(Display *dpy, const char *extname) 998 { 999 int majorrev, minorrev; 1000 XdbeScreenVisualInfo *svi; 1001 int numscreens = 0; 1002 1003 if (!XdbeQueryExtension(dpy, &majorrev, &minorrev)) 1004 return 0; 1005 1006 print_standard_extension_info(dpy, extname, majorrev, minorrev); 1007 svi = XdbeGetVisualInfo(dpy, (Drawable *)NULL, &numscreens); 1008 for (int iscrn = 0; iscrn < numscreens; iscrn++) 1009 { 1010 printf(" Double-buffered visuals on screen %d\n", iscrn); 1011 for (int ivis = 0; ivis < svi[iscrn].count; ivis++) 1012 { 1013 printf(" visual id 0x%lx depth %d perflevel %d\n", 1014 svi[iscrn].visinfo[ivis].visual, 1015 svi[iscrn].visinfo[ivis].depth, 1016 svi[iscrn].visinfo[ivis].perflevel); 1017 } 1018 } 1019 XdbeFreeVisualInfo(svi); 1020 return 1; 1021 } 1022 1023 static int 1024 print_record_info(Display *dpy, const char *extname) 1025 { 1026 int majorrev, minorrev; 1027 1028 if (!XRecordQueryVersion(dpy, &majorrev, &minorrev)) 1029 return 0; 1030 print_standard_extension_info(dpy, extname, majorrev, minorrev); 1031 return 1; 1032 } 1033 1034 #ifdef XINPUT 1035 static int 1036 print_xinput_info(Display *dpy, const char *extname) 1037 { 1038 int loop, num_extensions; 1039 char **extensions; 1040 XExtensionVersion *ext; 1041 1042 ext = XGetExtensionVersion(dpy, extname); 1043 1044 if (!ext || (ext == (XExtensionVersion*) NoSuchExtension)) 1045 return 0; 1046 1047 print_standard_extension_info(dpy, extname, ext->major_version, 1048 ext->minor_version); 1049 XFree(ext); 1050 1051 extensions = XListExtensions(dpy, &num_extensions); 1052 for (loop = 0; loop < num_extensions && 1053 (strcmp(extensions[loop], extname) != 0); loop++); 1054 XFreeExtensionList(extensions); 1055 if (loop != num_extensions) { 1056 int num_devices; 1057 XDeviceInfo *devices; 1058 1059 printf(" Extended devices :\n"); 1060 devices = XListInputDevices(dpy, &num_devices); 1061 for(loop=0; loop<num_devices; loop++) { 1062 printf(" \"%s\" [", devices[loop].name ? devices[loop].name : "<noname>"); 1063 switch(devices[loop].use) { 1064 case IsXPointer: 1065 printf("XPointer]\n"); 1066 break; 1067 case IsXKeyboard: 1068 printf("XKeyboard]\n"); 1069 break; 1070 case IsXExtensionDevice: 1071 printf("XExtensionDevice]\n"); 1072 break; 1073 #ifdef IsXExtensionKeyboard 1074 case IsXExtensionKeyboard: 1075 printf("XExtensionKeyboard]\n"); 1076 break; 1077 #endif 1078 #ifdef IsXExtensionPointer 1079 case IsXExtensionPointer: 1080 printf("XExtensionPointer]\n"); 1081 break; 1082 #endif 1083 default: 1084 printf("invalid value]\n"); 1085 break; 1086 } 1087 } 1088 XFreeDeviceList(devices); 1089 return 1; 1090 } 1091 else 1092 return 0; 1093 } 1094 #endif 1095 1096 #ifdef XRENDER 1097 static int 1098 print_xrender_info(Display *dpy, const char *extname) 1099 { 1100 int loop, num_extensions; 1101 char **extensions; 1102 int major, minor; 1103 1104 if (!XRenderQueryVersion (dpy, &major, &minor)) 1105 return 0; 1106 1107 print_standard_extension_info(dpy, extname, major, minor); 1108 1109 extensions = XListExtensions(dpy, &num_extensions); 1110 for (loop = 0; loop < num_extensions && 1111 (strcmp(extensions[loop], extname) != 0); loop++); 1112 XFreeExtensionList(extensions); 1113 if (loop != num_extensions) { 1114 XRenderPictFormat *pictform; 1115 1116 printf (" Render formats :\n"); 1117 for (int count = 0; (pictform = XRenderFindFormat (dpy, 0, NULL, count)); 1118 count++) 1119 { 1120 printf (" pict format:\n"); 1121 printf ("\tformat id: 0x%lx\n", pictform->id); 1122 printf ("\ttype: %s\n", 1123 pictform->type == PictTypeIndexed ? "Indexed" : "Direct"); 1124 printf ("\tdepth: %d\n", pictform->depth); 1125 if (pictform->type == PictTypeDirect) { 1126 printf("\talpha: %2d mask 0x%x\n", pictform->direct.alpha, pictform->direct.alphaMask); 1127 printf("\tred: %2d mask 0x%x\n", pictform->direct.red, pictform->direct.redMask); 1128 printf("\tgreen: %2d mask 0x%x\n", pictform->direct.green, pictform->direct.greenMask); 1129 printf("\tblue: %2d mask 0x%x\n", pictform->direct.blue, pictform->direct.blueMask); 1130 } 1131 else 1132 printf("\tcolormap 0x%lx\n", pictform->colormap); 1133 } 1134 printf (" Screen formats :\n"); 1135 for (int i = 0; i < ScreenCount (dpy); i++) { 1136 int nvi; /* number of elements returned */ 1137 XVisualInfo viproto; /* fill in for getting info */ 1138 XVisualInfo *vip; /* returned info */ 1139 int ndepths = 0, *depths = NULL; 1140 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 1141 XFilters *filters; 1142 #endif 1143 1144 nvi = 0; 1145 viproto.screen = i; 1146 vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi); 1147 printf (" Screen %d", i); 1148 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 1149 switch (XRenderQuerySubpixelOrder (dpy, i)) { 1150 case SubPixelUnknown: printf (" (sub-pixel order Unknown)"); break; 1151 case SubPixelHorizontalRGB: printf (" (sub-pixel order Horizontal RGB)"); break; 1152 case SubPixelHorizontalBGR: printf (" (sub-pixel order Horizontal BGR)"); break; 1153 case SubPixelVerticalRGB: printf (" (sub-pixel order Vertical RGB)"); break; 1154 case SubPixelVerticalBGR: printf (" (sub-pixel order Vertical BGR)"); break; 1155 case SubPixelNone: printf (" (sub-pixel order None)"); break; 1156 } 1157 printf ("\n"); 1158 filters = XRenderQueryFilters (dpy, RootWindow (dpy, i)); 1159 if (filters) 1160 { 1161 printf (" filters: "); 1162 for (int f = 0; f < filters->nfilter; f++) 1163 { 1164 printf ("%s", filters->filter[f]); 1165 if (f < filters->nalias && filters->alias[f] != FilterAliasNone) 1166 printf ("(%s)", filters->filter[filters->alias[f]]); 1167 if (f < filters->nfilter - 1) 1168 printf (", "); 1169 } 1170 XFree (filters); 1171 } 1172 #endif 1173 printf ("\n"); 1174 for (int j = 0; j < nvi; j++) 1175 { 1176 printf (" visual format:\n"); 1177 printf (" visual id: 0x%lx\n", vip[j].visualid); 1178 pictform = XRenderFindVisualFormat (dpy, vip[j].visual); 1179 if (pictform) 1180 printf(" pict format id: 0x%lx\n", pictform->id); 1181 else 1182 printf(" pict format id: None\n"); 1183 } 1184 if (vip) XFree ((char *) vip); 1185 depths = XListDepths (dpy, i, &ndepths); 1186 if (!depths) ndepths = 0; 1187 for (int j = 0; j < ndepths; j++) 1188 { 1189 XRenderPictFormat templ; 1190 1191 templ.depth = depths[j]; 1192 printf (" depth formats:\n"); 1193 printf (" depth %d\n", depths[j]); 1194 for (int count = 0; 1195 (pictform = XRenderFindFormat (dpy, PictFormatDepth, &templ, count)); 1196 count++) { 1197 printf(" pict format id: 0x%lx\n", pictform->id); 1198 } 1199 } 1200 if (depths) XFree (depths); 1201 } 1202 return 1; 1203 } 1204 else 1205 return 0; 1206 } 1207 #endif /* XRENDER */ 1208 1209 #ifdef COMPOSITE 1210 static int 1211 print_composite_info(Display *dpy, const char *extname) 1212 { 1213 int majorrev, minorrev, foo; 1214 1215 if (!XCompositeQueryExtension(dpy, &foo, &foo)) 1216 return 0; 1217 if (!XCompositeQueryVersion(dpy, &majorrev, &minorrev)) 1218 return 0; 1219 print_standard_extension_info(dpy, extname, majorrev, minorrev); 1220 return 1; 1221 } 1222 #endif 1223 1224 #ifdef PANORAMIX 1225 1226 static int 1227 print_xinerama_info(Display *dpy, const char *extname) 1228 { 1229 int majorrev, minorrev; 1230 1231 if (!XineramaQueryVersion (dpy, &majorrev, &minorrev)) 1232 return 0; 1233 1234 print_standard_extension_info(dpy, extname, majorrev, minorrev); 1235 1236 if (!XineramaIsActive(dpy)) { 1237 printf(" Xinerama is inactive.\n"); 1238 } else { 1239 int count = 0; 1240 XineramaScreenInfo *xineramaScreens = XineramaQueryScreens(dpy, &count); 1241 1242 for (int i = 0; i < count; i++) { 1243 XineramaScreenInfo *xs = &xineramaScreens[i]; 1244 printf(" head #%d: %dx%d @ %d,%d\n", xs->screen_number, 1245 xs->width, xs->height, xs->x_org, xs->y_org); 1246 } 1247 1248 XFree(xineramaScreens); 1249 } 1250 1251 return 1; 1252 } 1253 1254 #endif /* PANORAMIX */ 1255 1256 #ifdef DMX 1257 static const char *core(DMXInputAttributes *iinfo) 1258 { 1259 if (iinfo->isCore) return "core"; 1260 else if (iinfo->sendsCore) return "extension (sends core)"; 1261 else return "extension"; 1262 } 1263 1264 static int print_dmx_info(Display *dpy, const char *extname) 1265 { 1266 int event_base, error_base; 1267 int major_version, minor_version, patch_version; 1268 int count; 1269 1270 if (!DMXQueryExtension(dpy, &event_base, &error_base) 1271 || !DMXQueryVersion(dpy, &major_version, &minor_version, 1272 &patch_version)) return 0; 1273 print_standard_extension_info(dpy, extname, major_version, minor_version); 1274 printf(" Version stamp: %d\n", patch_version); 1275 1276 if (!DMXGetScreenCount(dpy, &count)) return 1; 1277 printf(" Screen count: %d\n", count); 1278 for (int i = 0; i < count; i++) { 1279 DMXScreenAttributes sinfo; 1280 1281 if (DMXGetScreenAttributes(dpy, i, &sinfo)) { 1282 printf(" %2d %s %ux%u+%d+%d %d @%dx%d\n", 1283 i, sinfo.displayName, 1284 sinfo.screenWindowWidth, sinfo.screenWindowHeight, 1285 sinfo.screenWindowXoffset, sinfo.screenWindowYoffset, 1286 sinfo.logicalScreen, 1287 sinfo.rootWindowXorigin, sinfo.rootWindowYorigin); 1288 } 1289 } 1290 1291 if (major_version != 1 1292 || minor_version < 1 1293 || !DMXGetInputCount(dpy, &count)) 1294 return 1; 1295 1296 printf(" Input count = %d\n", count); 1297 for (int i = 0; i < count; i++) { 1298 DMXInputAttributes iinfo; 1299 #ifdef XINPUT 1300 Display *backend; 1301 char *backendname = NULL; 1302 #endif 1303 if (DMXGetInputAttributes(dpy, i, &iinfo)) { 1304 switch (iinfo.inputType) { 1305 case DMXLocalInputType: 1306 printf(" %2d local %s", i, core(&iinfo)); 1307 break; 1308 case DMXConsoleInputType: 1309 printf(" %2d console %s %s", i, core(&iinfo), 1310 iinfo.name); 1311 break; 1312 case DMXBackendInputType: 1313 #ifdef XINPUT 1314 if (iinfo.physicalId >= 0) { 1315 if ((backend = XOpenDisplay(iinfo.name))) { 1316 XExtensionVersion *ext 1317 = XGetExtensionVersion(backend, INAME); 1318 if (ext 1319 && ext != (XExtensionVersion *)NoSuchExtension) { 1320 1321 int dcount; 1322 XDeviceInfo *devInfo = XListInputDevices(backend, 1323 &dcount); 1324 if (devInfo) { 1325 for (int d = 0; d < dcount; d++) { 1326 if ((unsigned)iinfo.physicalId 1327 == devInfo[d].id 1328 && devInfo[d].name) { 1329 backendname = strdup(devInfo[d].name); 1330 break; 1331 } 1332 } 1333 XFreeDeviceList(devInfo); 1334 } 1335 } 1336 XCloseDisplay(backend); 1337 } 1338 } 1339 #endif 1340 printf(" %2d backend %s o%d/%s",i, core(&iinfo), 1341 iinfo.physicalScreen, iinfo.name); 1342 if (iinfo.physicalId >= 0) printf("/id%d", iinfo.physicalId); 1343 #ifdef XINPUT 1344 if (backendname) { 1345 printf("=%s", backendname); 1346 free(backendname); 1347 } 1348 #endif 1349 break; 1350 } 1351 } 1352 printf("\n"); 1353 } 1354 return 1; 1355 } 1356 1357 #endif /* DMX */ 1358 1359 1360 #ifdef PRESENT 1361 static inline void print_present_capabilities(uint32_t capabilities) 1362 { 1363 if (capabilities == PresentCapabilityNone) { 1364 fputs("PresentCapabilityNone", stdout); 1365 } 1366 else { 1367 int count = 0; 1368 1369 if (capabilities & PresentCapabilityAsync) { 1370 fputs("PresentCapabilityAsync", stdout); 1371 count++; 1372 capabilities &= ~PresentCapabilityAsync; 1373 } 1374 if (capabilities & PresentCapabilityFence) { 1375 if (count) 1376 fputs(" | ", stdout); 1377 fputs("PresentCapabilityFence", stdout); 1378 count++; 1379 capabilities &= ~PresentCapabilityFence; 1380 } 1381 if (capabilities & PresentCapabilityUST) { 1382 if (count) 1383 fputs(" | ", stdout); 1384 fputs("PresentCapabilityUST", stdout); 1385 count++; 1386 capabilities &= ~PresentCapabilityUST; 1387 } 1388 #ifdef PresentCapabilityAsyncMayTear /* added in xorgproto-2023.1 */ 1389 if (capabilities & PresentCapabilityAsyncMayTear) { 1390 if (count) 1391 fputs(" | ", stdout); 1392 fputs("PresentCapabilityAsyncMayTear", stdout); 1393 count++; 1394 capabilities &= ~PresentCapabilityAsyncMayTear; 1395 } 1396 #endif 1397 #ifdef PresentCapabilitySyncobj /* added in xorgproto-2024.1 */ 1398 if (capabilities & PresentCapabilitySyncobj) { 1399 if (count) 1400 fputs(" | ", stdout); 1401 fputs("PresentCapabilitySyncobj", stdout); 1402 count++; 1403 capabilities &= ~PresentCapabilitySyncobj; 1404 } 1405 #endif 1406 /* Are there any bits left we didn't recognize? */ 1407 if (capabilities != 0) { 1408 for (unsigned int b = 0; b < 32; b++) { 1409 uint32_t m = 1U << b; 1410 1411 if (capabilities & m) { 1412 if (count) 1413 fputs(" | ", stdout); 1414 printf("PresentCapabilityUnknownBit%d", b); 1415 capabilities &= ~m; 1416 } 1417 } 1418 } 1419 } 1420 } 1421 1422 1423 static int print_present_info(Display *dpy, const char *extname) 1424 { 1425 int opcode, event_base, error_base; 1426 int major_version, minor_version; 1427 Bool query_crtcs = False; 1428 1429 if (!XPresentQueryExtension(dpy, &opcode, &event_base, &error_base) 1430 || !XPresentQueryVersion(dpy, &major_version, &minor_version)) 1431 return 0; 1432 print_standard_extension_info(dpy, extname, major_version, minor_version); 1433 1434 if (XRRQueryExtension (dpy, &event_base, &error_base)) { 1435 int rr_major, rr_minor; 1436 1437 if (XRRQueryVersion (dpy, &rr_major, &rr_minor) && 1438 (rr_major == 1) && (rr_minor >= 2)) { 1439 query_crtcs = True; 1440 } 1441 } 1442 1443 for (int i = 0; i < ScreenCount (dpy); i++) { 1444 Window screen_root = RootWindow(dpy, i); 1445 uint32_t capabilities = XPresentQueryCapabilities(dpy, screen_root); 1446 1447 printf(" screen #%d capabilities: 0x%x (", i, capabilities); 1448 print_present_capabilities(capabilities); 1449 puts(")"); 1450 1451 if (query_crtcs) { 1452 XRRScreenResources *res = XRRGetScreenResources (dpy, screen_root); 1453 1454 if (res != NULL) { 1455 for (int c = 0; c < res->ncrtc; c++) { 1456 capabilities = XPresentQueryCapabilities(dpy, res->crtcs[c]); 1457 printf(" crtc 0x%lx capabilities: 0x%x (", 1458 res->crtcs[c], capabilities); 1459 print_present_capabilities(capabilities); 1460 puts(")"); 1461 } 1462 XRRFreeScreenResources(res); 1463 } 1464 } 1465 } 1466 1467 return 1; 1468 } 1469 #endif /* XPRESENT */ 1470 1471 /* utilities to manage the list of recognized extensions */ 1472 1473 1474 typedef int (*ExtensionPrintFunc)( 1475 Display *, const char * 1476 ); 1477 1478 typedef struct { 1479 const char *extname; 1480 ExtensionPrintFunc printfunc; 1481 Bool printit; 1482 } ExtensionPrintInfo; 1483 1484 static ExtensionPrintInfo known_extensions[] = 1485 { 1486 #ifdef MITSHM 1487 {"MIT-SHM", print_mitshm_info, False}, 1488 #endif /* MITSHM */ 1489 #ifdef XKB 1490 {XkbName, print_xkb_info, False}, 1491 #endif /* XKB */ 1492 #ifdef MULTIBUFFER 1493 {MULTIBUFFER_PROTOCOL_NAME, print_multibuf_info, False}, 1494 #endif 1495 {"SHAPE", print_shape_info, False}, 1496 {SYNC_NAME, print_sync_info, False}, 1497 #ifdef XFreeXDGA 1498 {XF86DGANAME, print_dga_info, False}, 1499 #endif /* XFreeXDGA */ 1500 #ifdef XF86VIDMODE 1501 {XF86VIDMODENAME, print_XF86VidMode_info, False}, 1502 #endif /* XF86VIDMODE */ 1503 #ifdef XF86MISC 1504 {XF86MISCNAME, print_XF86Misc_info, False}, 1505 #endif /* XF86MISC */ 1506 {XTestExtensionName, print_xtest_info, False}, 1507 {"DOUBLE-BUFFER", print_dbe_info, False}, 1508 {"RECORD", print_record_info, False}, 1509 #ifdef XINPUT 1510 {INAME, print_xinput_info, False}, 1511 #endif 1512 #ifdef XRENDER 1513 {RENDER_NAME, print_xrender_info, False}, 1514 #endif 1515 #ifdef COMPOSITE 1516 {COMPOSITE_NAME, print_composite_info, False}, 1517 #endif 1518 #ifdef PANORAMIX 1519 {"XINERAMA", print_xinerama_info, False}, 1520 #endif 1521 #ifdef DMX 1522 {"DMX", print_dmx_info, False}, 1523 #endif 1524 #ifdef PRESENT 1525 {"Present", print_present_info, False}, 1526 #endif 1527 /* add new extensions here */ 1528 }; 1529 1530 static const int num_known_extensions = sizeof known_extensions / sizeof known_extensions[0]; 1531 1532 static void 1533 print_known_extensions(FILE *f) 1534 { 1535 int i, col; 1536 for (i = 0, col = 6; i < num_known_extensions; i++) 1537 { 1538 int extlen = (int) strlen(known_extensions[i].extname) + 1; 1539 1540 if ((col + extlen) > 79) 1541 { 1542 col = 6; 1543 fprintf(f, "\n "); 1544 } 1545 fprintf(f, "%s ", known_extensions[i].extname); 1546 col += extlen; 1547 } 1548 } 1549 1550 static void 1551 mark_extension_for_printing(const char *extname) 1552 { 1553 if (strcmp(extname, "all") == 0) 1554 { 1555 for (int i = 0; i < num_known_extensions; i++) 1556 known_extensions[i].printit = True; 1557 } 1558 else 1559 { 1560 for (int i = 0; i < num_known_extensions; i++) 1561 { 1562 if (strcmp(extname, known_extensions[i].extname) == 0) 1563 { 1564 known_extensions[i].printit = True; 1565 return; 1566 } 1567 } 1568 printf("%s extension not supported by %s\n", extname, ProgramName); 1569 } 1570 } 1571 1572 static void 1573 print_marked_extensions(Display *dpy) 1574 { 1575 for (int i = 0; i < num_known_extensions; i++) 1576 { 1577 if (known_extensions[i].printit) 1578 { 1579 printf("\n"); 1580 if (! (*known_extensions[i].printfunc)(dpy, 1581 known_extensions[i].extname)) 1582 { 1583 printf("%s extension not supported by server\n", 1584 known_extensions[i].extname); 1585 } 1586 } 1587 } 1588 } 1589 1590 static void _X_NORETURN 1591 usage(int exitstatus) 1592 { 1593 fprintf (stderr, "usage: %s [options]\n%s", ProgramName, 1594 "-display displayname\tserver to query\n" 1595 "-help\t\t\tprint program usage and exit\n" 1596 "-version\t\tprint program version and exit\n" 1597 "-queryExtensions\tprint info returned by XQueryExtension\n" 1598 "-ext all\t\tprint detailed info for all supported extensions\n" 1599 "-ext extension-name\tprint detailed info for extension-name if one of:\n "); 1600 print_known_extensions(stderr); 1601 fprintf (stderr, "\n"); 1602 exit (exitstatus); 1603 } 1604 1605 int 1606 main(int argc, char *argv[]) 1607 { 1608 Display *dpy; /* X connection */ 1609 char *displayname = NULL; /* server to contact */ 1610 1611 ProgramName = argv[0]; 1612 1613 for (int i = 1; i < argc; i++) { 1614 char *arg = argv[i]; 1615 size_t len = strlen(arg); 1616 1617 if (!strncmp("-display", arg, len)) { 1618 if (++i >= argc) { 1619 fprintf (stderr, "%s: -display requires an argument\n", 1620 ProgramName); 1621 usage (EXIT_FAILURE); 1622 } 1623 displayname = argv[i]; 1624 } else if (!strncmp("-queryExtensions", arg, len)) { 1625 queryExtensions = True; 1626 } else if (!strncmp("-ext", arg, len)) { 1627 if (++i >= argc) { 1628 fprintf (stderr, "%s: -ext requires an argument\n", 1629 ProgramName); 1630 usage (EXIT_FAILURE); 1631 } 1632 mark_extension_for_printing(argv[i]); 1633 } else if (!strncmp("-version", arg, len) || 1634 !strncmp("--version", arg, len)) { 1635 printf("%s\n", PACKAGE_STRING); 1636 exit (EXIT_SUCCESS); 1637 } else if (!strncmp("-help", arg, len) || 1638 !strncmp("--help", arg, len)) { 1639 usage (EXIT_SUCCESS); 1640 } else { 1641 fprintf (stderr, "%s: unrecognized argument '%s'\n", 1642 ProgramName, arg); 1643 usage (EXIT_FAILURE); 1644 } 1645 } 1646 1647 dpy = XOpenDisplay (displayname); 1648 if (!dpy) { 1649 fprintf (stderr, "%s: unable to open display \"%s\".\n", 1650 ProgramName, XDisplayName (displayname)); 1651 exit (EXIT_FAILURE); 1652 } 1653 1654 print_display_info (dpy); 1655 for (int i = 0; i < ScreenCount (dpy); i++) { 1656 print_screen_info (dpy, i); 1657 } 1658 1659 print_marked_extensions(dpy); 1660 1661 XCloseDisplay (dpy); 1662 exit (EXIT_SUCCESS); 1663 } 1664