1074 lines
30 KiB
C
1074 lines
30 KiB
C
/*
|
|
* $TOG: xdpyinfo.c /main/35 1998/02/09 13:57:05 kaleb $
|
|
*
|
|
* xdpyinfo - print information about X display connecton
|
|
*
|
|
*
|
|
Copyright 1988, 1998 The Open Group
|
|
|
|
All Rights Reserved.
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from The Open Group.
|
|
*
|
|
* Author: Jim Fulton, MIT X Consortium
|
|
* GLX and Overlay support added by Jamie Zawinski <jwz@jwz.org>, 11-Nov-99
|
|
*
|
|
* To compile:
|
|
* cc -DHAVE_GLX glxdpyinfo.c -o glxdpyinfo -lGL -lX11 -lXext -lm
|
|
*
|
|
* Other defines to consider:
|
|
* -DHAVE_XIE -DHAVE_XTEST -DHAVE_XRECORD
|
|
*/
|
|
|
|
#define HAVE_GLX /* added by Brian Paul */
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xproto.h> /* for CARD32 */
|
|
#include <X11/extensions/multibuf.h>
|
|
#ifdef HAVE_XIE
|
|
#include <X11/extensions/XIElib.h>
|
|
#endif /* HAVE_XIE */
|
|
#ifdef HAVE_XTEST
|
|
#include <X11/extensions/XTest.h>
|
|
#endif /* HAVE_XTEST */
|
|
#include <X11/extensions/sync.h>
|
|
#include <X11/extensions/Xdbe.h>
|
|
#ifdef HAVE_XRECORD
|
|
#include <X11/extensions/record.h>
|
|
#endif /* HAVE_XRECORD */
|
|
#ifdef MITSHM
|
|
#include <X11/extensions/XShm.h>
|
|
#endif
|
|
#include <X11/Xos.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef HAVE_GLX
|
|
# include <GL/gl.h>
|
|
# include <GL/glx.h>
|
|
#endif /* HAVE_GLX */
|
|
|
|
#define HAVE_OVERLAY /* jwz: no compile-time deps, so do this all the time */
|
|
|
|
char *ProgramName;
|
|
Bool queryExtensions = False;
|
|
|
|
static int StrCmp(a, b)
|
|
char **a, **b;
|
|
{
|
|
return strcmp(*a, *b);
|
|
}
|
|
|
|
|
|
#ifdef HAVE_GLX /* Added by jwz, 11-Nov-99 */
|
|
|
|
static void
|
|
print_glx_versions (dpy)
|
|
Display *dpy;
|
|
{
|
|
/* Note: with Mesa 3.0, this lies: it prints the info from the
|
|
client's GL library, rather than the info from the GLX server.
|
|
|
|
Note also that we can't protect these calls by only doing
|
|
them when the GLX extension is present, because with Mesa,
|
|
the server doesn't have that extension (but the GL library
|
|
works anyway.)
|
|
*/
|
|
int scr = DefaultScreen (dpy);
|
|
const char *vend, *vers;
|
|
vend = glXQueryServerString (dpy, scr, GLX_VENDOR);
|
|
if (!vend) return;
|
|
vers = glXQueryServerString (dpy, scr, GLX_VERSION);
|
|
printf ("GLX vendor: %s (%s)\n",
|
|
vend, (vers ? vers : "unknown version"));
|
|
}
|
|
|
|
static void
|
|
print_glx_visual_info (dpy, vip)
|
|
Display *dpy;
|
|
XVisualInfo *vip;
|
|
{
|
|
int status, value = False;
|
|
|
|
status = glXGetConfig (dpy, vip, GLX_USE_GL, &value);
|
|
if (status == GLX_NO_EXTENSION)
|
|
/* dpy does not support the GLX extension. */
|
|
return;
|
|
|
|
if (status == GLX_BAD_VISUAL || value == False)
|
|
{
|
|
printf (" GLX supported: no\n");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
printf (" GLX supported: yes\n");
|
|
}
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_LEVEL, &value) &&
|
|
value != 0)
|
|
printf (" GLX level: %d\n", value);
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_RGBA, &value) && value)
|
|
{
|
|
int r=0, g=0, b=0, a=0;
|
|
glXGetConfig (dpy, vip, GLX_RED_SIZE, &r);
|
|
glXGetConfig (dpy, vip, GLX_GREEN_SIZE, &g);
|
|
glXGetConfig (dpy, vip, GLX_BLUE_SIZE, &b);
|
|
glXGetConfig (dpy, vip, GLX_ALPHA_SIZE, &a);
|
|
printf (" GLX type: RGBA (%2d, %2d, %2d, %2d)\n",
|
|
r, g, b, a);
|
|
|
|
r=0, g=0, b=0, a=0;
|
|
glXGetConfig (dpy, vip, GLX_ACCUM_RED_SIZE, &r);
|
|
glXGetConfig (dpy, vip, GLX_ACCUM_GREEN_SIZE, &g);
|
|
glXGetConfig (dpy, vip, GLX_ACCUM_BLUE_SIZE, &b);
|
|
glXGetConfig (dpy, vip, GLX_ACCUM_ALPHA_SIZE, &a);
|
|
printf (" GLX accum: RGBA (%2d, %2d, %2d, %2d)\n",
|
|
r, g, b, a);
|
|
}
|
|
else
|
|
{
|
|
value = 0;
|
|
glXGetConfig (dpy, vip, GLX_BUFFER_SIZE, &value);
|
|
printf (" GLX type: indexed (%d)\n", value);
|
|
}
|
|
|
|
# if 0 /* redundant */
|
|
if (!glXGetConfig (dpy, vip, GLX_X_VISUAL_TYPE_EXT, &value))
|
|
printf (" GLX class: %s\n",
|
|
(value == GLX_TRUE_COLOR_EXT ? "TrueColor" :
|
|
value == GLX_DIRECT_COLOR_EXT ? "DirectColor" :
|
|
value == GLX_PSEUDO_COLOR_EXT ? "PseudoColor" :
|
|
value == GLX_STATIC_COLOR_EXT ? "StaticColor" :
|
|
value == GLX_GRAY_SCALE_EXT ? "Grayscale" :
|
|
value == GLX_STATIC_GRAY_EXT ? "StaticGray" : "???"));
|
|
# endif
|
|
|
|
# ifdef GLX_VISUAL_CAVEAT_EXT
|
|
if (!glXGetConfig (dpy, vip, GLX_VISUAL_CAVEAT_EXT, &value) &&
|
|
value != GLX_NONE_EXT)
|
|
printf (" GLX rating: %s\n",
|
|
(value == GLX_NONE_EXT ? "none" :
|
|
value == GLX_SLOW_VISUAL_EXT ? "slow" :
|
|
# ifdef GLX_NON_CONFORMANT_EXT
|
|
value == GLX_NON_CONFORMANT_EXT ? "non-conformant" :
|
|
# endif
|
|
"???"));
|
|
# endif
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_DOUBLEBUFFER, &value))
|
|
printf (" GLX double-buffer: %s\n", (value ? "yes" : "no"));
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_STEREO, &value) &&
|
|
value)
|
|
printf (" GLX stereo: %s\n", (value ? "yes" : "no"));
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_AUX_BUFFERS, &value) &&
|
|
value != 0)
|
|
printf (" GLX aux buffers: %d\n", value);
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_DEPTH_SIZE, &value))
|
|
printf (" GLX depth size: %d\n", value);
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_STENCIL_SIZE, &value) &&
|
|
value != 0)
|
|
printf (" GLX stencil size: %d\n", value);
|
|
|
|
# ifdef GLX_SAMPLE_BUFFERS_SGIS
|
|
if (!glXGetConfig (dpy, vip, GLX_SAMPLE_BUFFERS_SGIS, &value) &&
|
|
value != 0)
|
|
{
|
|
int bufs = value;
|
|
if (!glXGetConfig (dpy, vip, GLX_SAMPLES_SGIS, &value))
|
|
printf (" GLX multisamplers: %d (%d)\n", bufs, value);
|
|
}
|
|
# endif
|
|
|
|
if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_TYPE_EXT, &value) &&
|
|
value != GLX_NONE_EXT)
|
|
{
|
|
if (value == GLX_NONE_EXT)
|
|
printf (" GLX transparency: none\n");
|
|
else if (value == GLX_TRANSPARENT_INDEX_EXT)
|
|
{
|
|
if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_INDEX_VALUE_EXT,&value))
|
|
printf (" GLX transparency: indexed (%d)\n", value);
|
|
}
|
|
else if (value == GLX_TRANSPARENT_RGB_EXT)
|
|
{
|
|
int r=0, g=0, b=0, a=0;
|
|
glXGetConfig (dpy, vip, GLX_TRANSPARENT_RED_VALUE_EXT, &r);
|
|
glXGetConfig (dpy, vip, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g);
|
|
glXGetConfig (dpy, vip, GLX_TRANSPARENT_BLUE_VALUE_EXT, &b);
|
|
glXGetConfig (dpy, vip, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a);
|
|
printf (" GLX transparency: RGBA (%2d, %2d, %2d, %2d)\n",
|
|
r, g, b, a);
|
|
}
|
|
}
|
|
}
|
|
#endif /* HAVE_GLX */
|
|
|
|
|
|
#ifdef HAVE_OVERLAY /* Added by jwz, 11-Nov-99 */
|
|
|
|
/* If the server's root window contains a SERVER_OVERLAY_VISUALS property,
|
|
then that identifies the visuals which correspond to the video hardware's
|
|
overlay planes. Windows created in these kinds of visuals may have
|
|
transparent pixels that let other layers shine through.
|
|
|
|
This might not be an X Consortium standard, but it turns out that
|
|
SGI, HP, DEC, and IBM all use this same mechanism. So that's close
|
|
enough for me.
|
|
|
|
Documentation on the SERVER_OVERLAY_VISUALS property can be found at:
|
|
http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/server_overlay_visuals.html
|
|
*/
|
|
|
|
struct overlay
|
|
{
|
|
CARD32 visual_id;
|
|
CARD32 transparency; /* 0: none; 1: pixel; 2: mask */
|
|
CARD32 value; /* the transparent pixel */
|
|
CARD32 layer; /* -1: underlay; 0: normal; 1: popup; 2: overlay */
|
|
};
|
|
|
|
struct overlay_list
|
|
{
|
|
int count;
|
|
struct overlay *list;
|
|
};
|
|
|
|
static struct overlay_list *overlays = 0;
|
|
|
|
static void
|
|
find_overlay_info (dpy)
|
|
Display *dpy;
|
|
{
|
|
int screen;
|
|
Atom OVERLAY = XInternAtom (dpy, "SERVER_OVERLAY_VISUALS", False);
|
|
|
|
overlays = (struct overlay_list *) calloc (sizeof (struct overlay_list),
|
|
ScreenCount (dpy));
|
|
|
|
for (screen = 0; screen < ScreenCount (dpy); screen++)
|
|
{
|
|
Window window = RootWindow (dpy, screen);
|
|
Atom actual_type;
|
|
int actual_format;
|
|
unsigned long nitems, bytes_after;
|
|
struct overlay *data = 0;
|
|
int result = XGetWindowProperty (dpy, window, OVERLAY,
|
|
0, (65536 / sizeof (long)), False,
|
|
OVERLAY, &actual_type, &actual_format,
|
|
&nitems, &bytes_after,
|
|
(unsigned char **) &data);
|
|
if (result == Success &&
|
|
actual_type == OVERLAY &&
|
|
actual_format == 32 &&
|
|
nitems > 0)
|
|
{
|
|
overlays[screen].count = (nitems /
|
|
(sizeof(struct overlay) / sizeof(CARD32)));
|
|
overlays[screen].list = data;
|
|
}
|
|
else if (data)
|
|
XFree((char *) data);
|
|
}
|
|
}
|
|
|
|
static void
|
|
print_overlay_visual_info (vip)
|
|
XVisualInfo *vip;
|
|
{
|
|
int i;
|
|
int vis = vip->visualid;
|
|
int scr = vip->screen;
|
|
if (!overlays) return;
|
|
for (i = 0; i < overlays[scr].count; i++)
|
|
if (vis == overlays[scr].list[i].visual_id)
|
|
{
|
|
struct overlay *ov = &overlays[scr].list[i];
|
|
printf (" Overlay info: layer %ld (%s), ",
|
|
(long) ov->layer,
|
|
(ov->layer == -1 ? "underlay" :
|
|
ov->layer == 0 ? "normal" :
|
|
ov->layer == 1 ? "popup" :
|
|
ov->layer == 2 ? "overlay" : "???"));
|
|
if (ov->transparency == 1)
|
|
printf ("transparent pixel %lu\n", (unsigned long) ov->value);
|
|
else if (ov->transparency == 2)
|
|
printf ("transparent mask 0x%x\n", (unsigned long) ov->value);
|
|
else
|
|
printf ("opaque\n");
|
|
}
|
|
}
|
|
#endif /* HAVE_OVERLAY */
|
|
|
|
|
|
void
|
|
print_extension_info (dpy)
|
|
Display *dpy;
|
|
{
|
|
int n = 0;
|
|
char **extlist = XListExtensions (dpy, &n);
|
|
|
|
printf ("number of extensions: %d\n", n);
|
|
|
|
if (extlist) {
|
|
register int i;
|
|
int opcode, event, error;
|
|
|
|
qsort(extlist, n, sizeof(char *), StrCmp);
|
|
for (i = 0; i < n; i++) {
|
|
if (!queryExtensions) {
|
|
printf (" %s\n", extlist[i]);
|
|
continue;
|
|
}
|
|
XQueryExtension(dpy, extlist[i], &opcode, &event, &error);
|
|
printf (" %s (opcode: %d", extlist[i], opcode);
|
|
if (event)
|
|
printf (", base event: %d", event);
|
|
if (error)
|
|
printf (", base error: %d", error);
|
|
printf(")\n");
|
|
}
|
|
/* do not free, Xlib can depend on contents being unaltered */
|
|
/* XFreeExtensionList (extlist); */
|
|
}
|
|
}
|
|
|
|
void
|
|
print_display_info (dpy)
|
|
Display *dpy;
|
|
{
|
|
char dummybuf[40];
|
|
char *cp;
|
|
int minkeycode, maxkeycode;
|
|
int i, n;
|
|
long req_size;
|
|
XPixmapFormatValues *pmf;
|
|
Window focuswin;
|
|
int focusrevert;
|
|
|
|
printf ("name of display: %s\n", DisplayString (dpy));
|
|
printf ("version number: %d.%d\n",
|
|
ProtocolVersion (dpy), ProtocolRevision (dpy));
|
|
printf ("vendor string: %s\n", ServerVendor (dpy));
|
|
printf ("vendor release number: %d\n", VendorRelease (dpy));
|
|
|
|
#ifdef HAVE_GLX
|
|
print_glx_versions (dpy);
|
|
#endif /* HAVE_GLX */
|
|
|
|
req_size = XExtendedMaxRequestSize (dpy);
|
|
if (!req_size) req_size = XMaxRequestSize (dpy);
|
|
printf ("maximum request size: %ld bytes\n", req_size * 4);
|
|
printf ("motion buffer size: %d\n", XDisplayMotionBufferSize (dpy));
|
|
|
|
switch (BitmapBitOrder (dpy)) {
|
|
case LSBFirst: cp = "LSBFirst"; break;
|
|
case MSBFirst: cp = "MSBFirst"; break;
|
|
default:
|
|
sprintf (dummybuf, "unknown order %d", BitmapBitOrder (dpy));
|
|
cp = dummybuf;
|
|
break;
|
|
}
|
|
printf ("bitmap unit, bit order, padding: %d, %s, %d\n",
|
|
BitmapUnit (dpy), cp, BitmapPad (dpy));
|
|
|
|
switch (ImageByteOrder (dpy)) {
|
|
case LSBFirst: cp = "LSBFirst"; break;
|
|
case MSBFirst: cp = "MSBFirst"; break;
|
|
default:
|
|
sprintf (dummybuf, "unknown order %d", ImageByteOrder (dpy));
|
|
cp = dummybuf;
|
|
break;
|
|
}
|
|
printf ("image byte order: %s\n", cp);
|
|
|
|
pmf = XListPixmapFormats (dpy, &n);
|
|
printf ("number of supported pixmap formats: %d\n", n);
|
|
if (pmf) {
|
|
printf ("supported pixmap formats:\n");
|
|
for (i = 0; i < n; i++) {
|
|
printf (" depth %d, bits_per_pixel %d, scanline_pad %d\n",
|
|
pmf[i].depth, pmf[i].bits_per_pixel, pmf[i].scanline_pad);
|
|
}
|
|
XFree ((char *) pmf);
|
|
}
|
|
|
|
|
|
/*
|
|
* when we get interfaces to the PixmapFormat stuff, insert code here
|
|
*/
|
|
|
|
XDisplayKeycodes (dpy, &minkeycode, &maxkeycode);
|
|
printf ("keycode range: minimum %d, maximum %d\n",
|
|
minkeycode, maxkeycode);
|
|
|
|
XGetInputFocus (dpy, &focuswin, &focusrevert);
|
|
printf ("focus: ");
|
|
switch (focuswin) {
|
|
case PointerRoot:
|
|
printf ("PointerRoot\n");
|
|
break;
|
|
case None:
|
|
printf ("None\n");
|
|
break;
|
|
default:
|
|
printf("window 0x%lx, revert to ", focuswin);
|
|
switch (focusrevert) {
|
|
case RevertToParent:
|
|
printf ("Parent\n");
|
|
break;
|
|
case RevertToNone:
|
|
printf ("None\n");
|
|
break;
|
|
case RevertToPointerRoot:
|
|
printf ("PointerRoot\n");
|
|
break;
|
|
default: /* should not happen */
|
|
printf ("%d\n", focusrevert);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
print_extension_info (dpy);
|
|
|
|
printf ("default screen number: %d\n", DefaultScreen (dpy));
|
|
printf ("number of screens: %d\n", ScreenCount (dpy));
|
|
}
|
|
|
|
void
|
|
print_visual_info (vip)
|
|
XVisualInfo *vip;
|
|
{
|
|
char errorbuf[40]; /* for sprintfing into */
|
|
char *class = NULL; /* for printing */
|
|
|
|
switch (vip->class) {
|
|
case StaticGray: class = "StaticGray"; break;
|
|
case GrayScale: class = "GrayScale"; break;
|
|
case StaticColor: class = "StaticColor"; break;
|
|
case PseudoColor: class = "PseudoColor"; break;
|
|
case TrueColor: class = "TrueColor"; break;
|
|
case DirectColor: class = "DirectColor"; break;
|
|
default:
|
|
sprintf (errorbuf, "unknown class %d", vip->class);
|
|
class = errorbuf;
|
|
break;
|
|
}
|
|
|
|
printf (" visual:\n");
|
|
printf (" visual id: 0x%lx\n", vip->visualid);
|
|
printf (" class: %s\n", class);
|
|
printf (" depth: %d plane%s\n", vip->depth,
|
|
vip->depth == 1 ? "" : "s");
|
|
if (vip->class == TrueColor || vip->class == DirectColor)
|
|
printf (" available colormap entries: %d per subfield\n",
|
|
vip->colormap_size);
|
|
else
|
|
printf (" available colormap entries: %d\n",
|
|
vip->colormap_size);
|
|
printf (" red, green, blue masks: 0x%lx, 0x%lx, 0x%lx\n",
|
|
vip->red_mask, vip->green_mask, vip->blue_mask);
|
|
printf (" significant bits in color specification: %d bits\n",
|
|
vip->bits_per_rgb);
|
|
}
|
|
|
|
void
|
|
print_screen_info (dpy, scr)
|
|
Display *dpy;
|
|
int scr;
|
|
{
|
|
Screen *s = ScreenOfDisplay (dpy, scr); /* opaque structure */
|
|
XVisualInfo viproto; /* fill in for getting info */
|
|
XVisualInfo *vip; /* retured info */
|
|
int nvi; /* number of elements returned */
|
|
int i; /* temp variable: iterator */
|
|
char eventbuf[80]; /* want 79 chars per line + nul */
|
|
static char *yes = "YES", *no = "NO", *when = "WHEN MAPPED";
|
|
double xres, yres;
|
|
int ndepths = 0, *depths = NULL;
|
|
unsigned int width, height;
|
|
|
|
|
|
/*
|
|
* there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
|
|
*
|
|
* dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
|
|
* = N pixels / (M inch / 25.4)
|
|
* = N * 25.4 pixels / M inch
|
|
*/
|
|
|
|
xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) /
|
|
((double) DisplayWidthMM(dpy,scr)));
|
|
yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) /
|
|
((double) DisplayHeightMM(dpy,scr)));
|
|
|
|
printf ("\n");
|
|
printf ("screen #%d:\n", scr);
|
|
printf (" dimensions: %dx%d pixels (%dx%d millimeters)\n",
|
|
DisplayWidth (dpy, scr), DisplayHeight (dpy, scr),
|
|
DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
|
|
printf (" resolution: %dx%d dots per inch\n",
|
|
(int) (xres + 0.5), (int) (yres + 0.5));
|
|
depths = XListDepths (dpy, scr, &ndepths);
|
|
if (!depths) ndepths = 0;
|
|
printf (" depths (%d): ", ndepths);
|
|
for (i = 0; i < ndepths; i++) {
|
|
printf ("%d", depths[i]);
|
|
if (i < ndepths - 1) {
|
|
putchar (',');
|
|
putchar (' ');
|
|
}
|
|
}
|
|
putchar ('\n');
|
|
if (depths) XFree ((char *) depths);
|
|
printf (" root window id: 0x%lx\n", RootWindow (dpy, scr));
|
|
printf (" depth of root window: %d plane%s\n",
|
|
DisplayPlanes (dpy, scr),
|
|
DisplayPlanes (dpy, scr) == 1 ? "" : "s");
|
|
printf (" number of colormaps: minimum %d, maximum %d\n",
|
|
MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
|
|
printf (" default colormap: 0x%lx\n", DefaultColormap (dpy, scr));
|
|
printf (" default number of colormap cells: %d\n",
|
|
DisplayCells (dpy, scr));
|
|
printf (" preallocated pixels: black %d, white %d\n",
|
|
BlackPixel (dpy, scr), WhitePixel (dpy, scr));
|
|
printf (" options: backing-store %s, save-unders %s\n",
|
|
(DoesBackingStore (s) == NotUseful) ? no :
|
|
((DoesBackingStore (s) == Always) ? yes : when),
|
|
DoesSaveUnders (s) ? yes : no);
|
|
XQueryBestSize (dpy, CursorShape, RootWindow (dpy, scr), 65535, 65535,
|
|
&width, &height);
|
|
if (width == 65535 && height == 65535)
|
|
printf (" largest cursor: unlimited\n");
|
|
else
|
|
printf (" largest cursor: %dx%d\n", width, height);
|
|
printf (" current input event mask: 0x%lx\n", EventMaskOfScreen (s));
|
|
(void) print_event_mask (eventbuf, 79, 4, EventMaskOfScreen (s));
|
|
|
|
|
|
nvi = 0;
|
|
viproto.screen = scr;
|
|
vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi);
|
|
printf (" number of visuals: %d\n", nvi);
|
|
printf (" default visual id: 0x%lx\n",
|
|
XVisualIDFromVisual (DefaultVisual (dpy, scr)));
|
|
for (i = 0; i < nvi; i++) {
|
|
print_visual_info (vip+i);
|
|
#ifdef HAVE_OVERLAY
|
|
print_overlay_visual_info (vip+i);
|
|
#endif /* HAVE_OVERLAY */
|
|
#ifdef HAVE_GLX
|
|
print_glx_visual_info (dpy, vip+i);
|
|
#endif /* HAVE_GLX */
|
|
}
|
|
if (vip) XFree ((char *) vip);
|
|
}
|
|
|
|
/*
|
|
* The following routine prints out an event mask, wrapping events at nice
|
|
* boundaries.
|
|
*/
|
|
|
|
#define MASK_NAME_WIDTH 25
|
|
|
|
static struct _event_table {
|
|
char *name;
|
|
long value;
|
|
} event_table[] = {
|
|
{ "KeyPressMask ", KeyPressMask },
|
|
{ "KeyReleaseMask ", KeyReleaseMask },
|
|
{ "ButtonPressMask ", ButtonPressMask },
|
|
{ "ButtonReleaseMask ", ButtonReleaseMask },
|
|
{ "EnterWindowMask ", EnterWindowMask },
|
|
{ "LeaveWindowMask ", LeaveWindowMask },
|
|
{ "PointerMotionMask ", PointerMotionMask },
|
|
{ "PointerMotionHintMask ", PointerMotionHintMask },
|
|
{ "Button1MotionMask ", Button1MotionMask },
|
|
{ "Button2MotionMask ", Button2MotionMask },
|
|
{ "Button3MotionMask ", Button3MotionMask },
|
|
{ "Button4MotionMask ", Button4MotionMask },
|
|
{ "Button5MotionMask ", Button5MotionMask },
|
|
{ "ButtonMotionMask ", ButtonMotionMask },
|
|
{ "KeymapStateMask ", KeymapStateMask },
|
|
{ "ExposureMask ", ExposureMask },
|
|
{ "VisibilityChangeMask ", VisibilityChangeMask },
|
|
{ "StructureNotifyMask ", StructureNotifyMask },
|
|
{ "ResizeRedirectMask ", ResizeRedirectMask },
|
|
{ "SubstructureNotifyMask ", SubstructureNotifyMask },
|
|
{ "SubstructureRedirectMask ", SubstructureRedirectMask },
|
|
{ "FocusChangeMask ", FocusChangeMask },
|
|
{ "PropertyChangeMask ", PropertyChangeMask },
|
|
{ "ColormapChangeMask ", ColormapChangeMask },
|
|
{ "OwnerGrabButtonMask ", OwnerGrabButtonMask },
|
|
{ NULL, 0 }};
|
|
|
|
int print_event_mask (buf, lastcol, indent, mask)
|
|
char *buf; /* string to write into */
|
|
int lastcol; /* strlen(buf)+1 */
|
|
int indent; /* amount by which to indent */
|
|
long mask; /* event mask */
|
|
{
|
|
struct _event_table *etp;
|
|
int len;
|
|
int bitsfound = 0;
|
|
|
|
buf[0] = buf[lastcol] = '\0'; /* just in case */
|
|
|
|
#define INDENT() { register int i; len = indent; \
|
|
for (i = 0; i < indent; i++) buf[i] = ' '; }
|
|
|
|
INDENT ();
|
|
|
|
for (etp = event_table; etp->name; etp++) {
|
|
if (mask & etp->value) {
|
|
if (len + MASK_NAME_WIDTH > lastcol) {
|
|
puts (buf);
|
|
INDENT ();
|
|
}
|
|
strcpy (buf+len, etp->name);
|
|
len += MASK_NAME_WIDTH;
|
|
bitsfound++;
|
|
}
|
|
}
|
|
|
|
if (bitsfound) puts (buf);
|
|
|
|
#undef INDENT
|
|
|
|
return (bitsfound);
|
|
}
|
|
|
|
void
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev)
|
|
Display *dpy;
|
|
char *extname;
|
|
int majorrev, minorrev;
|
|
{
|
|
int opcode, event, error;
|
|
|
|
printf("%s version %d.%d ", extname, majorrev, minorrev);
|
|
|
|
XQueryExtension(dpy, extname, &opcode, &event, &error);
|
|
printf ("opcode: %d", opcode);
|
|
if (event)
|
|
printf (", base event: %d", event);
|
|
if (error)
|
|
printf (", base error: %d", error);
|
|
printf("\n");
|
|
}
|
|
|
|
int
|
|
print_multibuf_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
int i, j; /* temp variable: iterator */
|
|
int nmono, nstereo; /* count */
|
|
XmbufBufferInfo *mono_info = NULL, *stereo_info = NULL; /* arrays */
|
|
static char *fmt =
|
|
" visual id, max buffers, depth: 0x%lx, %d, %d\n";
|
|
int scr = 0;
|
|
int majorrev, minorrev;
|
|
|
|
if (!XmbufGetVersion(dpy, &majorrev, &minorrev))
|
|
return 0;
|
|
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev);
|
|
|
|
for (i = 0; i < ScreenCount (dpy); i++)
|
|
{
|
|
if (!XmbufGetScreenInfo (dpy, RootWindow(dpy, scr), &nmono, &mono_info,
|
|
&nstereo, &stereo_info)) {
|
|
fprintf (stderr,
|
|
"%s: unable to get multibuffer info for screen %d\n",
|
|
ProgramName, scr);
|
|
} else {
|
|
printf (" screen %d number of mono multibuffer types: %d\n", i, nmono);
|
|
for (j = 0; j < nmono; j++) {
|
|
printf (fmt, mono_info[j].visualid, mono_info[j].max_buffers,
|
|
mono_info[j].depth);
|
|
}
|
|
printf (" number of stereo multibuffer types: %d\n", nstereo);
|
|
for (j = 0; j < nstereo; j++) {
|
|
printf (fmt, stereo_info[j].visualid,
|
|
stereo_info[j].max_buffers, stereo_info[j].depth);
|
|
}
|
|
if (mono_info) XFree ((char *) mono_info);
|
|
if (stereo_info) XFree ((char *) stereo_info);
|
|
}
|
|
}
|
|
return 1;
|
|
} /* end print_multibuf_info */
|
|
|
|
|
|
/* XIE stuff */
|
|
|
|
#ifdef HAVE_XIE
|
|
|
|
char *subset_names[] = { NULL, "FULL", "DIS" };
|
|
char *align_names[] = { NULL, "Alignable", "Arbitrary" };
|
|
char *group_names[] = { /* 0 */ "Default",
|
|
/* 2 */ "ColorAlloc",
|
|
/* 4 */ "Constrain",
|
|
/* 6 */ "ConvertFromRGB",
|
|
/* 8 */ "ConvertToRGB",
|
|
/* 10 */ "Convolve",
|
|
/* 12 */ "Decode",
|
|
/* 14 */ "Dither",
|
|
/* 16 */ "Encode",
|
|
/* 18 */ "Gamut",
|
|
/* 20 */ "Geometry",
|
|
/* 22 */ "Histogram",
|
|
/* 24 */ "WhiteAdjust"
|
|
};
|
|
|
|
int
|
|
print_xie_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
XieExtensionInfo *xieInfo;
|
|
int i;
|
|
int ntechs;
|
|
XieTechnique *techs;
|
|
XieTechniqueGroup prevGroup;
|
|
|
|
if (!XieInitialize(dpy, &xieInfo ))
|
|
return 0;
|
|
|
|
print_standard_extension_info(dpy, extname,
|
|
xieInfo->server_major_rev, xieInfo->server_minor_rev);
|
|
|
|
printf(" service class: %s\n", subset_names[xieInfo->service_class]);
|
|
printf(" alignment: %s\n", align_names[xieInfo->alignment]);
|
|
printf(" uncnst_mantissa: %d\n", xieInfo->uncnst_mantissa);
|
|
printf(" uncnst_min_exp: %d\n", xieInfo->uncnst_min_exp);
|
|
printf(" uncnst_max_exp: %d\n", xieInfo->uncnst_max_exp);
|
|
printf(" cnst_levels:");
|
|
for (i = 0; i < xieInfo->n_cnst_levels; i++)
|
|
printf(" %d", xieInfo->cnst_levels[i]);
|
|
printf("\n");
|
|
|
|
if (!XieQueryTechniques(dpy, xieValAll, &ntechs, &techs))
|
|
return 1;
|
|
|
|
prevGroup = -1;
|
|
|
|
for (i = 0; i < ntechs; i++)
|
|
{
|
|
if (techs[i].group != prevGroup)
|
|
{
|
|
printf(" technique group: %s\n", group_names[techs[i].group >> 1]);
|
|
prevGroup = techs[i].group;
|
|
}
|
|
printf(" %s\tspeed: %d needs_param: %s number: %d\n",
|
|
techs[i].name,
|
|
techs[i].speed, (techs[i].needs_param ? "True " : "False"),
|
|
techs[i].number);
|
|
}
|
|
return 1;
|
|
} /* end print_xie_info */
|
|
|
|
#endif /* HAVE_XIE */
|
|
|
|
|
|
#ifdef HAVE_XTEST
|
|
int
|
|
print_xtest_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
int majorrev, minorrev, foo;
|
|
|
|
if (!XTestQueryExtension(dpy, &foo, &foo, &majorrev, &minorrev))
|
|
return 0;
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev);
|
|
return 1;
|
|
}
|
|
#endif /* HAVE_XTEST */
|
|
|
|
int
|
|
print_sync_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
int majorrev, minorrev;
|
|
XSyncSystemCounter *syscounters;
|
|
int ncounters, i;
|
|
|
|
if (!XSyncInitialize(dpy, &majorrev, &minorrev))
|
|
return 0;
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev);
|
|
|
|
syscounters = XSyncListSystemCounters(dpy, &ncounters);
|
|
printf(" system counters: %d\n", ncounters);
|
|
for (i = 0; i < ncounters; i++)
|
|
{
|
|
printf(" %s id: 0x%08x resolution_lo: %d resolution_hi: %d\n",
|
|
syscounters[i].name, syscounters[i].counter,
|
|
XSyncValueLow32(syscounters[i].resolution),
|
|
XSyncValueHigh32(syscounters[i].resolution));
|
|
}
|
|
XSyncFreeSystemCounterList(syscounters);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
print_shape_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
int majorrev, minorrev;
|
|
|
|
if (!XShapeQueryVersion(dpy, &majorrev, &minorrev))
|
|
return 0;
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev);
|
|
return 1;
|
|
}
|
|
|
|
#ifdef MITSHM
|
|
int
|
|
print_mitshm_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
int majorrev, minorrev;
|
|
Bool sharedPixmaps;
|
|
|
|
if (!XShmQueryVersion(dpy, &majorrev, &minorrev, &sharedPixmaps))
|
|
return 0;
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev);
|
|
printf(" shared pixmaps: ");
|
|
if (sharedPixmaps)
|
|
{
|
|
int format = XShmPixmapFormat(dpy);
|
|
printf("yes, format: %d\n", format);
|
|
}
|
|
else
|
|
{
|
|
printf("no\n");
|
|
}
|
|
return 1;
|
|
}
|
|
#endif /* MITSHM */
|
|
|
|
int
|
|
print_dbe_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
int majorrev, minorrev;
|
|
XdbeScreenVisualInfo *svi;
|
|
int numscreens = 0;
|
|
int iscrn, ivis;
|
|
|
|
if (!XdbeQueryExtension(dpy, &majorrev, &minorrev))
|
|
return 0;
|
|
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev);
|
|
svi = XdbeGetVisualInfo(dpy, (Drawable *)NULL, &numscreens);
|
|
for (iscrn = 0; iscrn < numscreens; iscrn++)
|
|
{
|
|
printf(" Double-buffered visuals on screen %d\n", iscrn);
|
|
for (ivis = 0; ivis < svi[iscrn].count; ivis++)
|
|
{
|
|
printf(" visual id 0x%lx depth %d perflevel %d\n",
|
|
svi[iscrn].visinfo[ivis].visual,
|
|
svi[iscrn].visinfo[ivis].depth,
|
|
svi[iscrn].visinfo[ivis].perflevel);
|
|
}
|
|
}
|
|
XdbeFreeVisualInfo(svi);
|
|
return 1;
|
|
}
|
|
|
|
#ifdef HAVE_XRECORD
|
|
int
|
|
print_record_info(dpy, extname)
|
|
Display *dpy;
|
|
char *extname;
|
|
{
|
|
int majorrev, minorrev;
|
|
|
|
if (!XRecordQueryVersion(dpy, &majorrev, &minorrev))
|
|
return 0;
|
|
print_standard_extension_info(dpy, extname, majorrev, minorrev);
|
|
return 1;
|
|
}
|
|
#endif /* HAVE_XRECORD */
|
|
|
|
/* utilities to manage the list of recognized extensions */
|
|
|
|
|
|
typedef int (*ExtensionPrintFunc)(
|
|
#if NeedFunctionPrototypes
|
|
Display *, char *
|
|
#endif
|
|
);
|
|
|
|
typedef struct {
|
|
char *extname;
|
|
ExtensionPrintFunc printfunc;
|
|
Bool printit;
|
|
} ExtensionPrintInfo;
|
|
|
|
ExtensionPrintInfo known_extensions[] =
|
|
{
|
|
#ifdef MITSHM
|
|
{"MIT-SHM", print_mitshm_info, False},
|
|
#endif /* MITSHM */
|
|
{MULTIBUFFER_PROTOCOL_NAME, print_multibuf_info, False},
|
|
{"SHAPE", print_shape_info, False},
|
|
{SYNC_NAME, print_sync_info, False},
|
|
#ifdef HAVE_XIE
|
|
{xieExtName, print_xie_info, False},
|
|
#endif /* HAVE_XIE */
|
|
#ifdef HAVE_XTEST
|
|
{XTestExtensionName, print_xtest_info, False},
|
|
#endif /* HAVE_XTEST */
|
|
{"DOUBLE-BUFFER", print_dbe_info, False},
|
|
#ifdef HAVE_XRECORD
|
|
{"RECORD", print_record_info, False}
|
|
#endif /* HAVE_XRECORD */
|
|
/* add new extensions here */
|
|
/* wish list: PEX XKB LBX */
|
|
};
|
|
|
|
int num_known_extensions = sizeof known_extensions / sizeof known_extensions[0];
|
|
|
|
void
|
|
print_known_extensions(f)
|
|
FILE *f;
|
|
{
|
|
int i;
|
|
for (i = 0; i < num_known_extensions; i++)
|
|
{
|
|
fprintf(f, "%s ", known_extensions[i].extname);
|
|
}
|
|
}
|
|
|
|
void
|
|
mark_extension_for_printing(extname)
|
|
char *extname;
|
|
{
|
|
int i;
|
|
|
|
if (strcmp(extname, "all") == 0)
|
|
{
|
|
for (i = 0; i < num_known_extensions; i++)
|
|
known_extensions[i].printit = True;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < num_known_extensions; i++)
|
|
{
|
|
if (strcmp(extname, known_extensions[i].extname) == 0)
|
|
{
|
|
known_extensions[i].printit = True;
|
|
return;
|
|
}
|
|
}
|
|
printf("%s extension not supported by %s\n", extname, ProgramName);
|
|
}
|
|
}
|
|
|
|
void
|
|
print_marked_extensions(dpy)
|
|
Display *dpy;
|
|
{
|
|
int i;
|
|
for (i = 0; i < num_known_extensions; i++)
|
|
{
|
|
if (known_extensions[i].printit)
|
|
{
|
|
printf("\n");
|
|
if (! (*known_extensions[i].printfunc)(dpy,
|
|
known_extensions[i].extname))
|
|
{
|
|
printf("%s extension not supported by server\n",
|
|
known_extensions[i].extname);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void usage ()
|
|
{
|
|
fprintf (stderr, "usage: %s [options]\n", ProgramName);
|
|
fprintf (stderr, "-display displayname\tserver to query\n");
|
|
fprintf (stderr, "-queryExtensions\tprint info returned by XQueryExtension\n");
|
|
fprintf (stderr, "-ext all\t\tprint detailed info for all supported extensions\n");
|
|
fprintf (stderr, "-ext extension-name\tprint detailed info for extension-name if one of:\n ");
|
|
print_known_extensions(stderr);
|
|
fprintf (stderr, "\n");
|
|
exit (1);
|
|
}
|
|
|
|
int main (argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
Display *dpy; /* X connection */
|
|
char *displayname = NULL; /* server to contact */
|
|
int i; /* temp variable: iterator */
|
|
Bool multibuf = False;
|
|
int mbuf_event_base, mbuf_error_base;
|
|
|
|
ProgramName = argv[0];
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
char *arg = argv[i];
|
|
int len = strlen(arg);
|
|
|
|
if (!strncmp("-display", arg, len)) {
|
|
if (++i >= argc) usage ();
|
|
displayname = argv[i];
|
|
} else if (!strncmp("-queryExtensions", arg, len)) {
|
|
queryExtensions = True;
|
|
} else if (!strncmp("-ext", arg, len)) {
|
|
if (++i >= argc) usage ();
|
|
mark_extension_for_printing(argv[i]);
|
|
} else
|
|
usage ();
|
|
}
|
|
|
|
dpy = XOpenDisplay (displayname);
|
|
if (!dpy) {
|
|
fprintf (stderr, "%s: unable to open display \"%s\".\n",
|
|
ProgramName, XDisplayName (displayname));
|
|
exit (1);
|
|
}
|
|
|
|
#ifdef HAVE_OVERLAY
|
|
find_overlay_info (dpy);
|
|
#endif /* HAVE_OVERLAY */
|
|
|
|
print_display_info (dpy);
|
|
for (i = 0; i < ScreenCount (dpy); i++) {
|
|
print_screen_info (dpy, i);
|
|
}
|
|
|
|
print_marked_extensions(dpy);
|
|
|
|
XCloseDisplay (dpy);
|
|
exit (0);
|
|
}
|