Home | History | Annotate | Line # | Download | only in dist
      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