http://ftp.x.org/contrib/applications/xscreensaver-3.21.tar.gz
[xscreensaver] / driver / xdpyinfo.c
1 /*
2  * $ TOG: xdpyinfo.c /main/35 1998/02/09 13:57:05 kaleb $
3  * 
4  * xdpyinfo - print information about X display connecton
5  *
6  * 
7 Copyright 1988, 1998  The Open Group
8
9 All Rights Reserved.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24  *
25  * Author:  Jim Fulton, MIT X Consortium
26  *
27  * GLX and Overlay support added by Jamie Zawinski <jwz@jwz.org>, 11-Nov-99
28  *
29  *      To compile:
30  *         cc -DHAVE_GLX xdpyinfo.c -o xdpyinfo -lGL -lX11 -lXext -lm
31  *
32  *      Other defines to consider:
33  *         -DHAVE_XIE -DHAVE_XTEST -DHAVE_SYNC -DHAVE_XRECORD
34  */
35
36 #include <X11/Xlib.h>
37 #include <X11/Xutil.h>
38 #include <X11/Xproto.h> /* for CARD32 */
39 #include <X11/extensions/multibuf.h>
40 #ifdef HAVE_XIE
41 #include <X11/extensions/XIElib.h>
42 #endif /* HAVE_XIE */
43 #ifdef HAVE_XTEST
44 #include <X11/extensions/XTest.h>
45 #endif /* HAVE_XTEST */
46 #ifdef HAVE_XSYNC
47 #include <X11/extensions/sync.h>
48 #endif /* HAVE_XSYNC */
49 #include <X11/extensions/Xdbe.h>
50 #ifdef HAVE_XRECORD
51 #include <X11/extensions/record.h>
52 #endif /* HAVE_XRECORD */
53 #ifdef MITSHM
54 #include <X11/extensions/XShm.h>
55 #endif
56 #include <X11/Xos.h>
57 #include <stdio.h>
58
59 #ifdef HAVE_GLX
60 # include <GL/gl.h>
61 # include <GL/glx.h>
62 #endif /* HAVE_GLX */
63
64 #define HAVE_OVERLAY /* jwz: no compile-time deps, so do this all the time */
65
66 char *ProgramName;
67 Bool queryExtensions = False;
68
69 static int StrCmp(a, b)
70     char **a, **b;
71 {
72     return strcmp(*a, *b);
73 }
74
75
76 #ifdef HAVE_GLX  /* Added by jwz, 11-Nov-99 */
77
78 static void
79 print_glx_versions (dpy)
80     Display *dpy;
81 {
82   /* Note: with Mesa 3.0, this lies: it prints the info from the
83      client's GL library, rather than the info from the GLX server.
84
85      Note also that we can't protect these calls by only doing
86      them when the GLX extension is present, because with Mesa,
87      the server doesn't have that extension (but the GL library
88      works anyway.)
89    */
90       int scr = DefaultScreen (dpy);
91       const char *vend, *vers;
92       vend = glXQueryServerString (dpy, scr, GLX_VENDOR);
93       if (!vend) return;
94       vers = glXQueryServerString (dpy, scr, GLX_VERSION);
95       printf ("GLX vendor:    %s (%s)\n",
96               vend, (vers ? vers : "unknown version"));
97 }
98
99 static void
100 print_glx_visual_info (dpy, vip)
101     Display *dpy;
102     XVisualInfo *vip;
103 {
104   int status, value = False;
105
106   status = glXGetConfig (dpy, vip, GLX_USE_GL, &value);
107   if (status == GLX_NO_EXTENSION)
108     /* dpy does not support the GLX extension. */
109     return;
110
111   if (status == GLX_BAD_VISUAL || value == False)
112     {
113       printf ("    GLX supported:     no\n");
114       return;
115     }
116   else
117     {
118       printf ("    GLX supported:     yes\n");
119     }
120     
121   if (!glXGetConfig (dpy, vip, GLX_LEVEL, &value) &&
122       value != 0)
123     printf ("    GLX level:         %d\n", value);
124
125   if (!glXGetConfig (dpy, vip, GLX_RGBA, &value) && value)
126     {
127       int r=0, g=0, b=0, a=0;
128       glXGetConfig (dpy, vip, GLX_RED_SIZE,   &r);
129       glXGetConfig (dpy, vip, GLX_GREEN_SIZE, &g);
130       glXGetConfig (dpy, vip, GLX_BLUE_SIZE,  &b);
131       glXGetConfig (dpy, vip, GLX_ALPHA_SIZE, &a);
132       printf ("    GLX type:          RGBA (%2d, %2d, %2d, %2d)\n",
133               r, g, b, a);
134
135       r=0, g=0, b=0, a=0;
136       glXGetConfig (dpy, vip, GLX_ACCUM_RED_SIZE,   &r);
137       glXGetConfig (dpy, vip, GLX_ACCUM_GREEN_SIZE, &g);
138       glXGetConfig (dpy, vip, GLX_ACCUM_BLUE_SIZE,  &b);
139       glXGetConfig (dpy, vip, GLX_ACCUM_ALPHA_SIZE, &a);
140       printf ("    GLX accum:         RGBA (%2d, %2d, %2d, %2d)\n",
141               r, g, b, a);
142     }
143   else
144     {
145       value = 0;
146       glXGetConfig (dpy, vip, GLX_BUFFER_SIZE, &value);
147       printf ("    GLX type:          indexed (%d)\n", value);
148     }
149
150 # if 0  /* redundant */
151   if (!glXGetConfig (dpy, vip, GLX_X_VISUAL_TYPE_EXT, &value))
152       printf ("    GLX class:         %s\n",
153               (value == GLX_TRUE_COLOR_EXT ? "TrueColor" :
154                value == GLX_DIRECT_COLOR_EXT ? "DirectColor" :
155                value == GLX_PSEUDO_COLOR_EXT ? "PseudoColor" :
156                value == GLX_STATIC_COLOR_EXT ? "StaticColor" :
157                value == GLX_GRAY_SCALE_EXT ? "Grayscale" :
158                value == GLX_STATIC_GRAY_EXT ? "StaticGray" : "???"));
159 # endif
160
161 # ifdef GLX_VISUAL_CAVEAT_EXT
162   if (!glXGetConfig (dpy, vip, GLX_VISUAL_CAVEAT_EXT, &value) &&
163       value != GLX_NONE_EXT)
164     printf ("    GLX rating:        %s\n",
165             (value == GLX_NONE_EXT ? "none" :
166              value == GLX_SLOW_VISUAL_EXT ? "slow" :
167 #   ifdef GLX_NON_CONFORMANT_EXT
168              value == GLX_NON_CONFORMANT_EXT ? "non-conformant" :
169 #   endif
170              "???"));
171 # endif
172
173   if (!glXGetConfig (dpy, vip, GLX_DOUBLEBUFFER, &value))
174     printf ("    GLX double-buffer: %s\n", (value ? "yes" : "no"));
175
176   if (!glXGetConfig (dpy, vip, GLX_STEREO, &value) &&
177       value)
178     printf ("    GLX stereo:        %s\n", (value ? "yes" : "no"));
179
180   if (!glXGetConfig (dpy, vip, GLX_AUX_BUFFERS, &value) &&
181       value != 0)
182     printf ("    GLX aux buffers:   %d\n", value);
183
184   if (!glXGetConfig (dpy, vip, GLX_DEPTH_SIZE, &value))
185     printf ("    GLX depth size:    %d\n", value);
186
187   if (!glXGetConfig (dpy, vip, GLX_STENCIL_SIZE, &value) &&
188       value != 0)
189     printf ("    GLX stencil size:  %d\n", value);
190
191 # ifdef GLX_SAMPLE_BUFFERS_SGIS
192   if (!glXGetConfig (dpy, vip, GLX_SAMPLE_BUFFERS_SGIS, &value) &&
193       value != 0)
194     {
195       int bufs = value;
196       if (!glXGetConfig (dpy, vip, GLX_SAMPLES_SGIS, &value))
197         printf ("    GLX multisamplers: %d (%d)\n", bufs, value);
198     }
199 # endif
200
201   if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_TYPE_EXT, &value) &&
202       value != GLX_NONE_EXT)
203     {
204       if (value == GLX_NONE_EXT)
205         printf ("    GLX transparency:  none\n");
206       else if (value == GLX_TRANSPARENT_INDEX_EXT)
207         {
208           if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_INDEX_VALUE_EXT,&value))
209             printf ("    GLX transparency:  indexed (%d)\n", value);
210         }
211       else if (value == GLX_TRANSPARENT_RGB_EXT)
212         {
213           int r=0, g=0, b=0, a=0;
214           glXGetConfig (dpy, vip, GLX_TRANSPARENT_RED_VALUE_EXT,   &r);
215           glXGetConfig (dpy, vip, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g);
216           glXGetConfig (dpy, vip, GLX_TRANSPARENT_BLUE_VALUE_EXT,  &b);
217           glXGetConfig (dpy, vip, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a);
218           printf ("    GLX transparency:  RGBA (%2d, %2d, %2d, %2d)\n",
219                   r, g, b, a);
220         }
221     }
222 }
223 #endif /* HAVE_GLX */
224
225
226 #ifdef HAVE_OVERLAY  /* Added by jwz, 11-Nov-99 */
227
228  /* If the server's root window contains a SERVER_OVERLAY_VISUALS property,
229     then that identifies the visuals which correspond to the video hardware's
230     overlay planes.  Windows created in these kinds of visuals may have
231     transparent pixels that let other layers shine through.
232
233     This might not be an X Consortium standard, but it turns out that
234     SGI, HP, DEC, and IBM all use this same mechanism.  So that's close
235     enough for me.
236
237     Documentation on the SERVER_OVERLAY_VISUALS property can be found at:
238     http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/server_overlay_visuals.html
239   */
240
241 struct overlay
242 {
243   CARD32 visual_id;
244   CARD32 transparency;  /* 0: none; 1: pixel; 2: mask */
245   CARD32 value;         /* the transparent pixel */
246   CARD32 layer;         /* -1: underlay; 0: normal; 1: popup; 2: overlay */
247 };
248
249 struct overlay_list
250 {
251   int count;
252   struct overlay *list;
253 };
254
255 static struct overlay_list *overlays = 0;
256
257 static void
258 find_overlay_info (dpy)
259   Display *dpy;
260 {
261   int screen;
262   Atom OVERLAY = XInternAtom (dpy, "SERVER_OVERLAY_VISUALS", False);
263
264   overlays = (struct overlay_list *) calloc (sizeof (struct overlay_list),
265                                              ScreenCount (dpy));
266
267   for (screen = 0; screen < ScreenCount (dpy); screen++)
268     {
269       Window window = RootWindow (dpy, screen);
270       Atom actual_type;
271       int actual_format;
272       unsigned long nitems, bytes_after;
273       struct overlay *data = 0;
274       int result = XGetWindowProperty (dpy, window, OVERLAY,
275                                        0, (65536 / sizeof (long)), False, 
276                                        OVERLAY, &actual_type, &actual_format,
277                                        &nitems, &bytes_after,
278                                        (unsigned char **) &data);
279       if (result == Success &&
280           actual_type == OVERLAY &&
281           actual_format == 32 &&
282           nitems > 0)
283         {
284           overlays[screen].count = (nitems /
285                                     (sizeof(struct overlay) / sizeof(CARD32)));
286           overlays[screen].list = data;
287         }
288       else if (data)
289         XFree((char *) data);
290     }
291 }
292
293 static void
294 print_overlay_visual_info (vip)
295     XVisualInfo *vip;
296 {
297   int i;
298   int vis = vip->visualid;
299   int scr = vip->screen;
300   if (!overlays) return;
301   for (i = 0; i < overlays[scr].count; i++)
302     if (vis == overlays[scr].list[i].visual_id)
303       {
304         struct overlay *ov = &overlays[scr].list[i];
305         printf ("    Overlay info:      layer %ld (%s), ",
306                 (long) ov->layer,
307                 (ov->layer == -1 ? "underlay" :
308                  ov->layer ==  0 ? "normal" :
309                  ov->layer ==  1 ? "popup" :
310                  ov->layer ==  2 ? "overlay" : "???"));
311         if (ov->transparency == 1)
312           printf ("transparent pixel %lu\n", (unsigned long) ov->value);
313         else if (ov->transparency == 2)
314           printf ("transparent mask 0x%x\n", (unsigned long) ov->value);
315         else
316           printf ("opaque\n");
317       }
318 }
319 #endif /* HAVE_OVERLAY */
320
321
322 void
323 print_extension_info (dpy)
324     Display *dpy;
325 {
326     int n = 0;
327     char **extlist = XListExtensions (dpy, &n);
328
329     printf ("number of extensions:    %d\n", n);
330
331     if (extlist) {
332         register int i;
333         int opcode, event, error;
334
335         qsort(extlist, n, sizeof(char *), StrCmp);
336         for (i = 0; i < n; i++) {
337             if (!queryExtensions) {
338                 printf ("    %s\n", extlist[i]);
339                 continue;
340             }
341             XQueryExtension(dpy, extlist[i], &opcode, &event, &error);
342             printf ("    %s  (opcode: %d", extlist[i], opcode);
343             if (event)
344                 printf (", base event: %d", event);
345             if (error)
346                 printf (", base error: %d", error);
347             printf(")\n");
348         }
349         /* do not free, Xlib can depend on contents being unaltered */
350         /* XFreeExtensionList (extlist); */
351     }
352 }
353
354 void
355 print_display_info (dpy)
356     Display *dpy;
357 {
358     char dummybuf[40];
359     char *cp;
360     int minkeycode, maxkeycode;
361     int i, n;
362     long req_size;
363     XPixmapFormatValues *pmf;
364     Window focuswin;
365     int focusrevert;
366
367     printf ("name of display:    %s\n", DisplayString (dpy));
368     printf ("version number:    %d.%d\n",
369             ProtocolVersion (dpy), ProtocolRevision (dpy));
370     printf ("vendor string:    %s\n", ServerVendor (dpy));
371     printf ("vendor release number:    %d\n", VendorRelease (dpy));
372
373 #ifdef HAVE_GLX
374     print_glx_versions (dpy);
375 #endif /* HAVE_GLX */
376
377     req_size = XExtendedMaxRequestSize (dpy);
378     if (!req_size) req_size = XMaxRequestSize (dpy);
379     printf ("maximum request size:  %ld bytes\n", req_size * 4);
380     printf ("motion buffer size:  %d\n", XDisplayMotionBufferSize (dpy));
381
382     switch (BitmapBitOrder (dpy)) {
383       case LSBFirst:    cp = "LSBFirst"; break;
384       case MSBFirst:    cp = "MSBFirst"; break;
385       default:    
386         sprintf (dummybuf, "unknown order %d", BitmapBitOrder (dpy));
387         cp = dummybuf;
388         break;
389     }
390     printf ("bitmap unit, bit order, padding:    %d, %s, %d\n",
391             BitmapUnit (dpy), cp, BitmapPad (dpy));
392
393     switch (ImageByteOrder (dpy)) {
394       case LSBFirst:    cp = "LSBFirst"; break;
395       case MSBFirst:    cp = "MSBFirst"; break;
396       default:    
397         sprintf (dummybuf, "unknown order %d", ImageByteOrder (dpy));
398         cp = dummybuf;
399         break;
400     }
401     printf ("image byte order:    %s\n", cp);
402
403     pmf = XListPixmapFormats (dpy, &n);
404     printf ("number of supported pixmap formats:    %d\n", n);
405     if (pmf) {
406         printf ("supported pixmap formats:\n");
407         for (i = 0; i < n; i++) {
408             printf ("    depth %d, bits_per_pixel %d, scanline_pad %d\n",
409                     pmf[i].depth, pmf[i].bits_per_pixel, pmf[i].scanline_pad);
410         }
411         XFree ((char *) pmf);
412     }
413
414
415     /*
416      * when we get interfaces to the PixmapFormat stuff, insert code here
417      */
418
419     XDisplayKeycodes (dpy, &minkeycode, &maxkeycode);
420     printf ("keycode range:    minimum %d, maximum %d\n",
421             minkeycode, maxkeycode);
422
423     XGetInputFocus (dpy, &focuswin, &focusrevert);
424     printf ("focus:  ");
425     switch (focuswin) {
426       case PointerRoot:
427         printf ("PointerRoot\n");
428         break;
429       case None:
430         printf ("None\n");
431         break;
432       default:
433         printf("window 0x%lx, revert to ", focuswin);
434         switch (focusrevert) {
435           case RevertToParent:
436             printf ("Parent\n");
437             break;
438           case RevertToNone:
439             printf ("None\n");
440             break;
441           case RevertToPointerRoot:
442             printf ("PointerRoot\n");
443             break;
444           default:                      /* should not happen */
445             printf ("%d\n", focusrevert);
446             break;
447         }
448         break;
449     }
450
451     print_extension_info (dpy);
452
453     printf ("default screen number:    %d\n", DefaultScreen (dpy));
454     printf ("number of screens:    %d\n", ScreenCount (dpy));
455 }
456
457 void
458 print_visual_info (vip)
459     XVisualInfo *vip;
460 {
461     char errorbuf[40];                  /* for sprintfing into */
462     char *class = NULL;                 /* for printing */
463
464     switch (vip->class) {
465       case StaticGray:    class = "StaticGray"; break;
466       case GrayScale:    class = "GrayScale"; break;
467       case StaticColor:    class = "StaticColor"; break;
468       case PseudoColor:    class = "PseudoColor"; break;
469       case TrueColor:    class = "TrueColor"; break;
470       case DirectColor:    class = "DirectColor"; break;
471       default:    
472         sprintf (errorbuf, "unknown class %d", vip->class);
473         class = errorbuf;
474         break;
475     }
476
477     printf ("  visual:\n");
478     printf ("    visual id:    0x%lx\n", vip->visualid);
479     printf ("    class:    %s\n", class);
480     printf ("    depth:    %d plane%s\n", vip->depth, 
481             vip->depth == 1 ? "" : "s");
482     if (vip->class == TrueColor || vip->class == DirectColor)
483         printf ("    available colormap entries:    %d per subfield\n",
484                 vip->colormap_size);
485     else
486         printf ("    available colormap entries:    %d\n",
487                 vip->colormap_size);
488     printf ("    red, green, blue masks:    0x%lx, 0x%lx, 0x%lx\n",
489             vip->red_mask, vip->green_mask, vip->blue_mask);
490     printf ("    significant bits in color specification:    %d bits\n",
491             vip->bits_per_rgb);
492 }
493
494 void
495 print_screen_info (dpy, scr)
496     Display *dpy;
497     int scr;
498 {
499     Screen *s = ScreenOfDisplay (dpy, scr);  /* opaque structure */
500     XVisualInfo viproto;                /* fill in for getting info */
501     XVisualInfo *vip;                   /* retured info */
502     int nvi;                            /* number of elements returned */
503     int i;                              /* temp variable: iterator */
504     char eventbuf[80];                  /* want 79 chars per line + nul */
505     static char *yes = "YES", *no = "NO", *when = "WHEN MAPPED";
506     double xres, yres;
507     int ndepths = 0, *depths = NULL;
508     unsigned int width, height;
509
510
511     /*
512      * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
513      *
514      *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
515      *         = N pixels / (M inch / 25.4)
516      *         = N * 25.4 pixels / M inch
517      */
518
519     xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) / 
520             ((double) DisplayWidthMM(dpy,scr)));
521     yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) / 
522             ((double) DisplayHeightMM(dpy,scr)));
523
524     printf ("\n");
525     printf ("screen #%d:\n", scr);
526     printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
527             DisplayWidth (dpy, scr), DisplayHeight (dpy, scr),
528             DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
529     printf ("  resolution:    %dx%d dots per inch\n", 
530             (int) (xres + 0.5), (int) (yres + 0.5));
531     depths = XListDepths (dpy, scr, &ndepths);
532     if (!depths) ndepths = 0;
533     printf ("  depths (%d):    ", ndepths);
534     for (i = 0; i < ndepths; i++) {
535         printf ("%d", depths[i]);
536         if (i < ndepths - 1) { 
537             putchar (',');
538             putchar (' ');
539         }
540     }
541     putchar ('\n');
542     if (depths) XFree ((char *) depths);
543     printf ("  root window id:    0x%lx\n", RootWindow (dpy, scr));
544     printf ("  depth of root window:    %d plane%s\n",
545             DisplayPlanes (dpy, scr),
546             DisplayPlanes (dpy, scr) == 1 ? "" : "s");
547     printf ("  number of colormaps:    minimum %d, maximum %d\n",
548             MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
549     printf ("  default colormap:    0x%lx\n", DefaultColormap (dpy, scr));
550     printf ("  default number of colormap cells:    %d\n",
551             DisplayCells (dpy, scr));
552     printf ("  preallocated pixels:    black %d, white %d\n",
553             BlackPixel (dpy, scr), WhitePixel (dpy, scr));
554     printf ("  options:    backing-store %s, save-unders %s\n",
555             (DoesBackingStore (s) == NotUseful) ? no :
556             ((DoesBackingStore (s) == Always) ? yes : when),
557             DoesSaveUnders (s) ? yes : no);
558     XQueryBestSize (dpy, CursorShape, RootWindow (dpy, scr), 65535, 65535,
559                     &width, &height);
560     if (width == 65535 && height == 65535)
561         printf ("  largest cursor:    unlimited\n");
562     else
563         printf ("  largest cursor:    %dx%d\n", width, height);
564     printf ("  current input event mask:    0x%lx\n", EventMaskOfScreen (s));
565     (void) print_event_mask (eventbuf, 79, 4, EventMaskOfScreen (s));
566                       
567
568     nvi = 0;
569     viproto.screen = scr;
570     vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi);
571     printf ("  number of visuals:    %d\n", nvi);
572     printf ("  default visual id:  0x%lx\n", 
573             XVisualIDFromVisual (DefaultVisual (dpy, scr)));
574     for (i = 0; i < nvi; i++) {
575         print_visual_info (vip+i);
576 #ifdef HAVE_OVERLAY
577         print_overlay_visual_info (vip+i);
578 #endif /* HAVE_OVERLAY */
579 #ifdef HAVE_GLX
580         print_glx_visual_info (dpy, vip+i);
581 #endif /* HAVE_GLX */
582     }
583     if (vip) XFree ((char *) vip);
584 }
585
586 /*
587  * The following routine prints out an event mask, wrapping events at nice
588  * boundaries.
589  */
590
591 #define MASK_NAME_WIDTH 25
592
593 static struct _event_table {
594     char *name;
595     long value;
596 } event_table[] = {
597     { "KeyPressMask             ", KeyPressMask },
598     { "KeyReleaseMask           ", KeyReleaseMask },
599     { "ButtonPressMask          ", ButtonPressMask },
600     { "ButtonReleaseMask        ", ButtonReleaseMask },
601     { "EnterWindowMask          ", EnterWindowMask },
602     { "LeaveWindowMask          ", LeaveWindowMask },
603     { "PointerMotionMask        ", PointerMotionMask },
604     { "PointerMotionHintMask    ", PointerMotionHintMask },
605     { "Button1MotionMask        ", Button1MotionMask },
606     { "Button2MotionMask        ", Button2MotionMask },
607     { "Button3MotionMask        ", Button3MotionMask },
608     { "Button4MotionMask        ", Button4MotionMask },
609     { "Button5MotionMask        ", Button5MotionMask },
610     { "ButtonMotionMask         ", ButtonMotionMask },
611     { "KeymapStateMask          ", KeymapStateMask },
612     { "ExposureMask             ", ExposureMask },
613     { "VisibilityChangeMask     ", VisibilityChangeMask },
614     { "StructureNotifyMask      ", StructureNotifyMask },
615     { "ResizeRedirectMask       ", ResizeRedirectMask },
616     { "SubstructureNotifyMask   ", SubstructureNotifyMask },
617     { "SubstructureRedirectMask ", SubstructureRedirectMask },
618     { "FocusChangeMask          ", FocusChangeMask },
619     { "PropertyChangeMask       ", PropertyChangeMask },
620     { "ColormapChangeMask       ", ColormapChangeMask },
621     { "OwnerGrabButtonMask      ", OwnerGrabButtonMask },
622     { NULL, 0 }};
623
624 int print_event_mask (buf, lastcol, indent, mask)
625     char *buf;                          /* string to write into */
626     int lastcol;                        /* strlen(buf)+1 */
627     int indent;                         /* amount by which to indent */
628     long mask;                          /* event mask */
629 {
630     struct _event_table *etp;
631     int len;
632     int bitsfound = 0;
633
634     buf[0] = buf[lastcol] = '\0';       /* just in case */
635
636 #define INDENT() { register int i; len = indent; \
637                    for (i = 0; i < indent; i++) buf[i] = ' '; }
638
639     INDENT ();
640
641     for (etp = event_table; etp->name; etp++) {
642         if (mask & etp->value) {
643             if (len + MASK_NAME_WIDTH > lastcol) {
644                 puts (buf);
645                 INDENT ();
646             }
647             strcpy (buf+len, etp->name);
648             len += MASK_NAME_WIDTH;
649             bitsfound++;
650         }
651     }
652
653     if (bitsfound) puts (buf);
654
655 #undef INDENT
656
657     return (bitsfound);
658 }
659
660 void
661 print_standard_extension_info(dpy, extname, majorrev, minorrev)
662     Display *dpy;
663     char *extname;
664     int majorrev, minorrev;
665 {
666     int opcode, event, error;
667
668     printf("%s version %d.%d ", extname, majorrev, minorrev);
669
670     XQueryExtension(dpy, extname, &opcode, &event, &error);
671     printf ("opcode: %d", opcode);
672     if (event)
673         printf (", base event: %d", event);
674     if (error)
675         printf (", base error: %d", error);
676     printf("\n");
677 }
678
679 int
680 print_multibuf_info(dpy, extname)
681     Display *dpy;
682     char *extname;
683 {
684     int i, j;                   /* temp variable: iterator */
685     int nmono, nstereo;         /* count */
686     XmbufBufferInfo *mono_info = NULL, *stereo_info = NULL; /* arrays */
687     static char *fmt = 
688         "    visual id, max buffers, depth:    0x%lx, %d, %d\n";
689     int scr = 0;
690     int majorrev, minorrev;
691
692     if (!XmbufGetVersion(dpy, &majorrev, &minorrev))
693         return 0;
694
695     print_standard_extension_info(dpy, extname, majorrev, minorrev);
696
697     for (i = 0; i < ScreenCount (dpy); i++)
698     {
699         if (!XmbufGetScreenInfo (dpy, RootWindow(dpy, scr), &nmono, &mono_info,
700                                  &nstereo, &stereo_info)) {
701             fprintf (stderr,
702                      "%s:  unable to get multibuffer info for screen %d\n",
703                      ProgramName, scr);
704         } else {
705             printf ("  screen %d number of mono multibuffer types:    %d\n", i, nmono);
706             for (j = 0; j < nmono; j++) {
707                 printf (fmt, mono_info[j].visualid, mono_info[j].max_buffers,
708                         mono_info[j].depth);
709             }
710             printf ("  number of stereo multibuffer types:    %d\n", nstereo);
711             for (j = 0; j < nstereo; j++) {
712                 printf (fmt, stereo_info[j].visualid,
713                         stereo_info[j].max_buffers, stereo_info[j].depth);
714             }
715             if (mono_info) XFree ((char *) mono_info);
716             if (stereo_info) XFree ((char *) stereo_info);
717         }
718     }
719     return 1;
720 } /* end print_multibuf_info */
721
722
723 /* XIE stuff */
724
725 #ifdef HAVE_XIE
726
727 char *subset_names[] = { NULL, "FULL", "DIS" };
728 char *align_names[] = { NULL, "Alignable", "Arbitrary" };
729 char *group_names[] = { /* 0  */ "Default",
730                             /* 2  */ "ColorAlloc",
731                             /* 4  */ "Constrain",
732                             /* 6  */ "ConvertFromRGB",
733                             /* 8  */ "ConvertToRGB",
734                             /* 10 */ "Convolve",
735                             /* 12 */ "Decode",
736                             /* 14 */ "Dither",
737                             /* 16 */ "Encode",
738                             /* 18 */ "Gamut",
739                             /* 20 */ "Geometry",
740                             /* 22 */ "Histogram",
741                             /* 24 */ "WhiteAdjust"
742                             };
743
744 int
745 print_xie_info(dpy, extname)
746     Display *dpy;
747     char *extname;
748 {
749     XieExtensionInfo *xieInfo;
750     int i;
751     int ntechs;
752     XieTechnique *techs;
753     XieTechniqueGroup prevGroup;
754
755     if (!XieInitialize(dpy, &xieInfo ))
756         return 0;
757
758     print_standard_extension_info(dpy, extname,
759         xieInfo->server_major_rev, xieInfo->server_minor_rev);
760
761     printf("  service class: %s\n", subset_names[xieInfo->service_class]);
762     printf("  alignment: %s\n", align_names[xieInfo->alignment]);
763     printf("  uncnst_mantissa: %d\n", xieInfo->uncnst_mantissa);
764     printf("  uncnst_min_exp: %d\n", xieInfo->uncnst_min_exp);
765     printf("  uncnst_max_exp: %d\n", xieInfo->uncnst_max_exp);
766     printf("  cnst_levels:"); 
767     for (i = 0; i < xieInfo->n_cnst_levels; i++)
768         printf(" %d", xieInfo->cnst_levels[i]);
769     printf("\n");
770
771     if (!XieQueryTechniques(dpy, xieValAll, &ntechs, &techs))
772         return 1;
773
774     prevGroup = -1;
775
776     for (i = 0; i < ntechs; i++)
777     {
778         if (techs[i].group != prevGroup)
779         {
780             printf("  technique group: %s\n", group_names[techs[i].group >> 1]);
781             prevGroup = techs[i].group;
782         }
783         printf("    %s\tspeed: %d  needs_param: %s  number: %d\n",
784                techs[i].name,
785                techs[i].speed, (techs[i].needs_param ? "True " : "False"),
786                techs[i].number);
787     }
788     return 1;
789 } /* end print_xie_info */
790
791 #endif /* HAVE_XIE */
792
793
794 #ifdef HAVE_XTEST
795 int
796 print_xtest_info(dpy, extname)
797     Display *dpy;
798     char *extname;
799 {
800     int majorrev, minorrev, foo;
801
802     if (!XTestQueryExtension(dpy, &foo, &foo, &majorrev, &minorrev))
803         return 0;
804     print_standard_extension_info(dpy, extname, majorrev, minorrev);
805     return 1;
806 }
807 #endif /* HAVE_XTEST */
808
809 #ifdef HAVE_XSYNC
810 int
811 print_sync_info(dpy, extname)
812     Display *dpy;
813     char *extname;
814 {
815     int majorrev, minorrev;
816     XSyncSystemCounter *syscounters;
817     int ncounters, i;
818
819     if (!XSyncInitialize(dpy, &majorrev, &minorrev))
820         return 0;
821     print_standard_extension_info(dpy, extname, majorrev, minorrev);
822
823     syscounters = XSyncListSystemCounters(dpy, &ncounters);
824     printf("  system counters: %d\n", ncounters);
825     for (i = 0; i < ncounters; i++)
826     {
827         printf("    %s  id: 0x%08x  resolution_lo: %d  resolution_hi: %d\n",
828                syscounters[i].name, syscounters[i].counter,
829                XSyncValueLow32(syscounters[i].resolution),
830                XSyncValueHigh32(syscounters[i].resolution));
831     }
832     XSyncFreeSystemCounterList(syscounters);
833     return 1;
834 }
835 #endif /* HAVE_XSYNC */
836
837 int
838 print_shape_info(dpy, extname)
839     Display *dpy;
840     char *extname;
841 {
842     int majorrev, minorrev;
843
844     if (!XShapeQueryVersion(dpy, &majorrev, &minorrev))
845         return 0;
846     print_standard_extension_info(dpy, extname, majorrev, minorrev);
847     return 1;
848 }
849
850 #ifdef MITSHM
851 int
852 print_mitshm_info(dpy, extname)
853     Display *dpy;
854     char *extname;
855 {
856     int majorrev, minorrev;
857     Bool sharedPixmaps;
858
859     if (!XShmQueryVersion(dpy, &majorrev, &minorrev, &sharedPixmaps))
860         return 0;
861     print_standard_extension_info(dpy, extname, majorrev, minorrev);
862     printf("  shared pixmaps: ");
863     if (sharedPixmaps)
864     {
865         int format = XShmPixmapFormat(dpy);
866         printf("yes, format: %d\n", format);
867     }
868     else
869     {
870         printf("no\n");
871     }
872     return 1;
873 }
874 #endif /* MITSHM */
875
876 int
877 print_dbe_info(dpy, extname)
878     Display *dpy;
879     char *extname;
880 {
881     int majorrev, minorrev;
882     XdbeScreenVisualInfo *svi;
883     int numscreens = 0;
884     int iscrn, ivis;
885
886     if (!XdbeQueryExtension(dpy, &majorrev, &minorrev))
887         return 0;
888
889     print_standard_extension_info(dpy, extname, majorrev, minorrev);
890     svi = XdbeGetVisualInfo(dpy, (Drawable *)NULL, &numscreens);
891     for (iscrn = 0; iscrn < numscreens; iscrn++)
892     {
893         printf("  Double-buffered visuals on screen %d\n", iscrn);
894         for (ivis = 0; ivis < svi[iscrn].count; ivis++)
895         {
896             printf("    visual id 0x%lx  depth %d  perflevel %d\n",
897                    svi[iscrn].visinfo[ivis].visual,
898                    svi[iscrn].visinfo[ivis].depth,
899                    svi[iscrn].visinfo[ivis].perflevel);
900         }
901     }
902     XdbeFreeVisualInfo(svi);
903     return 1;
904 }
905
906 #ifdef HAVE_XRECORD
907 int
908 print_record_info(dpy, extname)
909     Display *dpy;
910     char *extname;
911 {
912     int majorrev, minorrev;
913
914     if (!XRecordQueryVersion(dpy, &majorrev, &minorrev))
915         return 0;
916     print_standard_extension_info(dpy, extname, majorrev, minorrev);
917     return 1;
918 }
919 #endif /* HAVE_XRECORD */
920
921 /* utilities to manage the list of recognized extensions */
922
923
924 typedef int (*ExtensionPrintFunc)(
925 #if NeedFunctionPrototypes
926     Display *, char *
927 #endif
928 );
929
930 typedef struct {
931     char *extname;
932     ExtensionPrintFunc printfunc;
933     Bool printit;
934 } ExtensionPrintInfo;
935
936 ExtensionPrintInfo known_extensions[] =
937 {
938 #ifdef MITSHM
939     {"MIT-SHM", print_mitshm_info, False},
940 #endif /* MITSHM */
941     {MULTIBUFFER_PROTOCOL_NAME, print_multibuf_info, False},
942     {"SHAPE", print_shape_info, False},
943 #ifdef HAVE_XSYNC
944     {SYNC_NAME, print_sync_info, False},
945 #endif /* HAVE_XSYNC */
946 #ifdef HAVE_XIE
947     {xieExtName, print_xie_info, False},
948 #endif /* HAVE_XIE */
949 #ifdef HAVE_XTEST
950     {XTestExtensionName, print_xtest_info, False},
951 #endif /* HAVE_XTEST */
952     {"DOUBLE-BUFFER", print_dbe_info, False},
953 #ifdef HAVE_XRECORD
954     {"RECORD", print_record_info, False}    
955 #endif /* HAVE_XRECORD */
956     /* add new extensions here */
957     /* wish list: PEX XKB LBX */
958 };
959
960 int num_known_extensions = sizeof known_extensions / sizeof known_extensions[0];
961
962 void
963 print_known_extensions(f)
964     FILE *f;
965 {
966     int i;
967     for (i = 0; i < num_known_extensions; i++)
968     {
969         fprintf(f, "%s ", known_extensions[i].extname);
970     }
971 }
972
973 void
974 mark_extension_for_printing(extname)
975     char *extname;
976 {
977     int i;
978
979     if (strcmp(extname, "all") == 0)
980     {
981         for (i = 0; i < num_known_extensions; i++)
982             known_extensions[i].printit = True;
983     }
984     else
985     {
986         for (i = 0; i < num_known_extensions; i++)
987         {
988             if (strcmp(extname, known_extensions[i].extname) == 0)
989             {
990                 known_extensions[i].printit = True;
991                 return;
992             }
993         }
994         printf("%s extension not supported by %s\n", extname, ProgramName);
995     }
996 }
997
998 void
999 print_marked_extensions(dpy)
1000     Display *dpy;
1001 {
1002     int i;
1003     for (i = 0; i < num_known_extensions; i++)
1004     {
1005         if (known_extensions[i].printit)
1006         {
1007             printf("\n");
1008             if (! (*known_extensions[i].printfunc)(dpy,
1009                                         known_extensions[i].extname))
1010             {
1011                 printf("%s extension not supported by server\n",
1012                        known_extensions[i].extname);
1013             }
1014         }
1015     }
1016 }
1017
1018 static void usage ()
1019 {
1020     fprintf (stderr, "usage:  %s [options]\n", ProgramName);
1021     fprintf (stderr, "-display displayname\tserver to query\n");
1022     fprintf (stderr, "-queryExtensions\tprint info returned by XQueryExtension\n");
1023     fprintf (stderr, "-ext all\t\tprint detailed info for all supported extensions\n");
1024     fprintf (stderr, "-ext extension-name\tprint detailed info for extension-name if one of:\n     ");
1025     print_known_extensions(stderr);
1026     fprintf (stderr, "\n");
1027     exit (1);
1028 }
1029
1030 int main (argc, argv)
1031     int argc;
1032     char *argv[];
1033 {
1034     Display *dpy;                       /* X connection */
1035     char *displayname = NULL;           /* server to contact */
1036     int i;                              /* temp variable:  iterator */
1037     Bool multibuf = False;
1038     int mbuf_event_base, mbuf_error_base;
1039
1040     ProgramName = argv[0];
1041
1042     for (i = 1; i < argc; i++) {
1043         char *arg = argv[i];
1044         int len = strlen(arg);
1045         
1046         if (!strncmp("-display", arg, len)) {
1047             if (++i >= argc) usage ();
1048             displayname = argv[i];
1049         } else if (!strncmp("-queryExtensions", arg, len)) {
1050             queryExtensions = True;
1051         } else if (!strncmp("-ext", arg, len)) {
1052             if (++i >= argc) usage ();
1053             mark_extension_for_printing(argv[i]);
1054         } else
1055             usage ();
1056     }
1057
1058     dpy = XOpenDisplay (displayname);
1059     if (!dpy) {
1060         fprintf (stderr, "%s:  unable to open display \"%s\".\n",
1061                  ProgramName, XDisplayName (displayname));
1062         exit (1);
1063     }
1064
1065 #ifdef HAVE_OVERLAY
1066         find_overlay_info (dpy);
1067 #endif /* HAVE_OVERLAY */
1068
1069     print_display_info (dpy);
1070     for (i = 0; i < ScreenCount (dpy); i++) {
1071         print_screen_info (dpy, i);
1072     }
1073
1074     print_marked_extensions(dpy);
1075
1076     XCloseDisplay (dpy);
1077     exit (0);
1078 }