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