aboutsummaryrefslogtreecommitdiff
path: root/apps/xwininfo/xwininfo.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-10-05 10:44:08 +0000
committermarha <marha@users.sourceforge.net>2010-10-05 10:44:08 +0000
commitbfa0c2fa423efa7ece6e54d5f30bbe95ca4bfc2a (patch)
tree37c4a2982fb317254b1ea14dd06c355f9da7826a /apps/xwininfo/xwininfo.c
parentfe234aa555e2b16ac7836fee297878a6e3efe343 (diff)
parent51f3d1e140307561f64c47dae1d44f912accb5cf (diff)
downloadvcxsrv-bfa0c2fa423efa7ece6e54d5f30bbe95ca4bfc2a.tar.gz
vcxsrv-bfa0c2fa423efa7ece6e54d5f30bbe95ca4bfc2a.tar.bz2
vcxsrv-bfa0c2fa423efa7ece6e54d5f30bbe95ca4bfc2a.zip
svn merge ^/branches/released .
Diffstat (limited to 'apps/xwininfo/xwininfo.c')
-rw-r--r--apps/xwininfo/xwininfo.c2414
1 files changed, 1629 insertions, 785 deletions
diff --git a/apps/xwininfo/xwininfo.c b/apps/xwininfo/xwininfo.c
index e5d70bcfb..db392bb2b 100644
--- a/apps/xwininfo/xwininfo.c
+++ b/apps/xwininfo/xwininfo.c
@@ -1,9 +1,28 @@
-/* $XdotOrg: $ */
-/* $Xorg: xwininfo.c,v 1.4 2001/02/09 02:06:04 xorgcvs Exp $ */
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
/*
Copyright 1987, 1998 The Open Group
-Copyright 1999 Sun Microsystems, Inc.
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
@@ -30,7 +49,6 @@ or other dealings in this Software without prior written authorization
of the copyright holder.
*/
-/* $XFree86: xc/programs/xwininfo/xwininfo.c,v 1.9 2003/09/09 22:08:25 herrb Exp $ */
/*
@@ -46,60 +64,213 @@ of the copyright holder.
*/
#include "config.h"
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/Xos.h>
-#include <X11/extensions/shape.h>
-#ifndef NO_I18N
-#include <X11/Xlocale.h>
+
+#include <xcb/xcb.h>
+#include <xcb/xproto.h>
+#ifdef USE_XCB_ICCCM
+# include <xcb/xcb_icccm.h>
#endif
+#include <xcb/shape.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
+#include <locale.h>
+#ifndef _MSC_VER
+#include <langinfo.h>
+#endif
+#ifdef HAVE_ICONV
+# include <iconv.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+
+#ifndef HAVE_STRNLEN
+#include "strnlen.h"
+#endif
/* Include routines to handle parsing defaults */
#include "dsimple.h"
typedef struct {
- long code;
- const char *name;
+ long code;
+ const char *name;
} binding;
-static void scale_init(void);
-static char *nscale(int, int, int, char *, size_t);
-static char *xscale(int);
-static char *yscale(int);
-static char *bscale(int);
-static int bad_window_handler(Display *, XErrorEvent *);
-int main(int, char **);
-static const char *LookupL(long, const binding *);
-static const char *Lookup(int, const binding *);
-static void Display_Window_Id(Window, int);
-static void Display_Stats_Info(Window);
-static void Display_Bits_Info(Window);
-static void Display_Event_Mask(long);
-static void Display_Events_Info(Window);
-static void Display_Tree_Info(Window, int);
-static void display_tree_info_1(Window, int, int);
-static void Display_Hints(XSizeHints *);
-static void Display_Size_Hints(Window);
-static void Display_Window_Shape(Window);
-static void Display_WM_Info(Window);
-
-static char *window_id_format = "0x%lx";
+#ifndef USE_XCB_ICCCM
+/* Once xcb-icccm's API is stable, this should be replaced by
+ xcb_size_hints_t & xcb_size_hints_flags_t */
+typedef struct {
+ /** User specified flags */
+ uint32_t flags;
+ /** User-specified position */
+ int32_t x, y;
+ /** User-specified size */
+ int32_t width, height;
+ /** Program-specified minimum size */
+ int32_t min_width, min_height;
+ /** Program-specified maximum size */
+ int32_t max_width, max_height;
+ /** Program-specified resize increments */
+ int32_t width_inc, height_inc;
+ /** Program-specified minimum aspect ratios */
+ int32_t min_aspect_num, min_aspect_den;
+ /** Program-specified maximum aspect ratios */
+ int32_t max_aspect_num, max_aspect_den;
+ /** Program-specified base size */
+ int32_t base_width, base_height;
+ /** Program-specified window gravity */
+ uint32_t win_gravity;
+} wm_size_hints_t;
+
+# define xcb_size_hints_t wm_size_hints_t
+
+typedef struct {
+ /** Marks which fields in this structure are defined */
+ int32_t flags;
+ /** Does this application rely on the window manager to get keyboard
+ input? */
+ uint32_t input;
+ /** See below */
+ int32_t initial_state;
+ /** Pixmap to be used as icon */
+ xcb_pixmap_t icon_pixmap;
+ /** Window to be used as icon */
+ xcb_window_t icon_window;
+ /** Initial position of icon */
+ int32_t icon_x, icon_y;
+ /** Icon mask bitmap */
+ xcb_pixmap_t icon_mask;
+ /* Identifier of related window group */
+ xcb_window_t window_group;
+} wm_hints_t;
+
+#define xcb_wm_hints_t wm_hints_t
+
+enum {
+ /* xcb_size_hints_flags_t */
+ XCB_SIZE_HINT_US_POSITION = 1 << 0,
+ XCB_SIZE_HINT_US_SIZE = 1 << 1,
+ XCB_SIZE_HINT_P_POSITION = 1 << 2,
+ XCB_SIZE_HINT_P_SIZE = 1 << 3,
+ XCB_SIZE_HINT_P_MIN_SIZE = 1 << 4,
+ XCB_SIZE_HINT_P_MAX_SIZE = 1 << 5,
+ XCB_SIZE_HINT_P_RESIZE_INC = 1 << 6,
+ XCB_SIZE_HINT_P_ASPECT = 1 << 7,
+ XCB_SIZE_HINT_BASE_SIZE = 1 << 8,
+ XCB_SIZE_HINT_P_WIN_GRAVITY = 1 << 9,
+ /* xcb_wm_state_t */
+ XCB_WM_STATE_WITHDRAWN = 0,
+ XCB_WM_STATE_NORMAL = 1,
+ XCB_WM_STATE_ICONIC = 3,
+ /* xcb_wm_t */
+ XCB_WM_HINT_INPUT = (1L << 0),
+ XCB_WM_HINT_STATE = (1L << 1),
+ XCB_WM_HINT_ICON_PIXMAP = (1L << 2),
+ XCB_WM_HINT_ICON_WINDOW = (1L << 3),
+ XCB_WM_HINT_ICON_POSITION = (1L << 4),
+ XCB_WM_HINT_ICON_MASK = (1L << 5),
+ XCB_WM_HINT_WINDOW_GROUP = (1L << 6),
+ XCB_WM_HINT_X_URGENCY = (1L << 8)
+};
+
+/* Once xcb-icccm's API is stable, these should be replaced by calls to it */
+# define GET_TEXT_PROPERTY(Dpy, Win, Atom) \
+ xcb_get_property (Dpy, False, Win, Atom, XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ)
+# define xcb_get_wm_name(Dpy, Win) GET_TEXT_PROPERTY(Dpy, Win, XCB_ATOM_WM_NAME)
+
+# define xcb_get_wm_class(Dpy, Win) \
+ xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, BUFSIZ)
+# define xcb_get_wm_hints(Dpy, Win) \
+ xcb_get_property(Dpy, False, Win, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9)
+
+# define xcb_get_wm_size_hints(Dpy, Win, Atom) \
+ xcb_get_property (Dpy, False, Win, Atom, XCB_ATOM_WM_SIZE_HINTS, 0, 18)
+# define xcb_get_wm_normal_hints(Dpy, Win) \
+ xcb_get_wm_size_hints(Dpy, Win, XCB_ATOM_WM_NORMAL_HINTS)
+#endif
+
+/* Possibly in xcb-emwh in the future? */
+static xcb_atom_t atom_net_wm_name, atom_utf8_string;
+static xcb_atom_t atom_net_wm_desktop, atom_net_wm_window_type,
+ atom_net_wm_state, atom_net_wm_pid, atom_net_frame_extents;
+static xcb_get_property_cookie_t get_net_wm_name (xcb_connection_t *,
+ xcb_window_t);
+
+/* Information we keep track of for each window to allow prefetching/reusing */
+struct wininfo {
+ xcb_window_t window;
+
+ /* cookies for requests we've sent */
+ xcb_get_geometry_cookie_t geometry_cookie;
+ xcb_get_property_cookie_t net_wm_name_cookie;
+ xcb_get_property_cookie_t wm_name_cookie;
+ xcb_get_property_cookie_t wm_class_cookie;
+ xcb_translate_coordinates_cookie_t trans_coords_cookie;
+ xcb_query_tree_cookie_t tree_cookie;
+ xcb_get_window_attributes_cookie_t attr_cookie;
+ xcb_get_property_cookie_t normal_hints_cookie;
+ xcb_get_property_cookie_t hints_cookie;
+ xcb_get_property_cookie_t wm_desktop_cookie;
+ xcb_get_property_cookie_t wm_window_type_cookie;
+ xcb_get_property_cookie_t wm_state_cookie;
+ xcb_get_property_cookie_t wm_pid_cookie;
+ xcb_get_property_cookie_t wm_client_machine_cookie;
+ xcb_get_property_cookie_t frame_extents_cookie;
+ xcb_get_property_cookie_t zoom_cookie;
+
+ /* cached results from previous requests */
+ xcb_get_geometry_reply_t * geometry;
+ xcb_get_window_attributes_reply_t * win_attributes;
+ xcb_size_hints_t * normal_hints;
+};
+
+static void scale_init (xcb_screen_t *scrn);
+static char *nscale (int, int, int, char *, size_t);
+static char *xscale (int);
+static char *yscale (int);
+static char *bscale (int);
+int main (int, char **);
+static const char *LookupL (long, const binding *);
+static const char *Lookup (int, const binding *);
+static void Display_Window_Id (struct wininfo *, Bool);
+static void Display_Stats_Info (struct wininfo *);
+static void Display_Bits_Info (struct wininfo *);
+static void Display_Event_Mask (long);
+static void Display_Events_Info (struct wininfo *);
+static void Display_Tree_Info (struct wininfo *, int);
+static void display_tree_info_1 (struct wininfo *, int, int);
+static void Display_Hints (xcb_size_hints_t *);
+static void Display_Size_Hints (struct wininfo *);
+static void Display_Window_Shape (xcb_window_t);
+static void Display_WM_Info (struct wininfo *);
+static void wininfo_wipe (struct wininfo *);
+
+static const char *window_id_format = "0x%lx";
+
+#ifdef HAVE_ICONV
+static iconv_t iconv_from_utf8;
+#endif
+static const char *user_encoding;
+static void print_utf8 (const char *, char *, size_t, const char *);
+static void print_friendly_name (const char *, const char *, const char *);
+
+static xcb_connection_t *dpy;
+static xcb_screen_t *screen;
+static xcb_generic_error_t *err;
#ifndef HAVE_STRLCAT
-static size_t strlcat(char *dst, const char *src, size_t dstsize)
+static size_t strlcat (char *dst, const char *src, size_t dstsize)
{
- size_t sd = strlen(dst);
- size_t ss = strlen(src);
+ size_t sd = strlen (dst);
+ size_t ss = strlen (src);
size_t s = sd + ss;
-
+
if (s < dstsize) {
- strcpy(dst + sd, src);
+ strcpy (dst + sd, src);
} else {
- strncpy(dst + sd, src, dstsize-sd-1);
+ strncpy (dst + sd, src, dstsize-sd-1);
dst[dstsize] = '\0';
}
return s;
@@ -110,50 +281,31 @@ static size_t strlcat(char *dst, const char *src, size_t dstsize)
* Report the syntax for calling xwininfo:
*/
void
-usage(void)
+usage (void)
{
fprintf (stderr,
- "usage: %s [-options ...]\n\n", program_name);
- fprintf (stderr,
- "where options include:\n");
- fprintf (stderr,
- " -help print this message\n");
- fprintf (stderr,
- " -display host:dpy X server to contact\n");
- fprintf (stderr,
- " -root use the root window\n");
- fprintf (stderr,
- " -id windowid use the window with the specified id\n");
- fprintf (stderr,
- " -name windowname use the window with the specified name\n");
- fprintf (stderr,
- " -int print window id in decimal\n");
- fprintf (stderr,
- " -children print parent and child identifiers\n");
- fprintf (stderr,
- " -tree print children identifiers recursively\n");
- fprintf (stderr,
- " -stats print window geometry [DEFAULT]\n");
- fprintf (stderr,
- " -bits print window pixel information\n");
- fprintf (stderr,
- " -events print events selected for on window\n");
- fprintf (stderr,
- " -size print size hints\n");
- fprintf (stderr,
- " -wm print window manager hints\n");
- fprintf (stderr,
- " -shape print shape extents\n");
- fprintf (stderr,
- " -frame don't ignore window manager frames\n");
- fprintf (stderr,
- " -english print sizes in english units\n");
- fprintf (stderr,
- " -metric print sizes in metric units\n");
- fprintf (stderr,
- " -all -tree, -stats, -bits, -events, -wm, -size, -shape\n");
- fprintf (stderr,
- "\n");
+ "usage: %s [-options ...]\n\n"
+ "where options include:\n"
+ " -help print this message\n"
+ " -display host:dpy X server to contact\n"
+ " -root use the root window\n"
+ " -id windowid use the window with the specified id\n"
+ " -name windowname use the window with the specified name\n"
+ " -int print window id in decimal\n"
+ " -children print parent and child identifiers\n"
+ " -tree print children identifiers recursively\n"
+ " -stats print window geometry [DEFAULT]\n"
+ " -bits print window pixel information\n"
+ " -events print events selected for on window\n"
+ " -size print size hints\n"
+ " -wm print window manager hints\n"
+ " -shape print shape extents\n"
+ " -frame don't ignore window manager frames\n"
+ " -english print sizes in english units\n"
+ " -metric print sizes in metric units\n"
+ " -all -tree, -stats, -bits, -events, -wm, -size, -shape\n"
+ "\n",
+ program_name);
exit (1);
}
@@ -168,21 +320,20 @@ usage(void)
*
*/
-#define getdsp(var,fn) var = fn(dpy, DefaultScreen(dpy))
-static int xp=0, xmm=0;
-static int yp=0, ymm=0;
-static int bp=0, bmm=0;
+static int xp = 0, xmm = 0;
+static int yp = 0, ymm = 0;
+static int bp = 0, bmm = 0;
static int english = 0, metric = 0;
static void
-scale_init(void)
+scale_init (xcb_screen_t *screen)
{
- getdsp(yp, DisplayHeight);
- getdsp(ymm, DisplayHeightMM);
- getdsp(xp, DisplayWidth);
- getdsp(xmm, DisplayWidthMM);
- bp = xp + yp;
- bmm = xmm + ymm;
+ xp = screen->width_in_pixels;
+ yp = screen->height_in_pixels;
+ xmm = screen->width_in_millimeters;
+ ymm = screen->height_in_millimeters;
+ bp = xp + yp;
+ bmm = xmm + ymm;
}
#define MILE (5280*12)
@@ -190,17 +341,17 @@ scale_init(void)
#define FOOT (12)
static char *
-nscale(int n, int np, int nmm, char *nbuf, size_t nbufsize)
+nscale (int n, int np, int nmm, char *nbuf, size_t nbufsize)
{
int s;
- snprintf(nbuf, nbufsize, "%d", n);
-
+ snprintf (nbuf, nbufsize, "%d", n);
+
if (metric||english) {
- s = strlcat(nbuf, " (", nbufsize);
+ s = strlcat (nbuf, " (", nbufsize);
if (metric) {
- snprintf(nbuf+s, nbufsize-s, "%.2f mm%s",
- ((double) n)*nmm/np, english ? "; " : "");
+ snprintf (nbuf+s, nbufsize-s, "%.2f mm%s",
+ ((double) n) * nmm/np , english ? "; " : "");
}
if (english) {
double inch_frac;
@@ -213,229 +364,391 @@ nscale(int n, int np, int nmm, char *nbuf, size_t nbufsize)
if (inr >= MILE) {
mi = inr/MILE;
inr %= MILE;
- s = strlen(nbuf);
- snprintf(nbuf+s, nbufsize-s, "%d %s(?!?)",
- mi, (mi==1) ? "mile" : "miles");
+ s = strlen (nbuf);
+ snprintf (nbuf+s, nbufsize-s, "%d %s(?!?)",
+ mi, (mi == 1) ? "mile" : "miles");
printed_anything = True;
}
if (inr >= YARD) {
yar = inr/YARD;
inr %= YARD;
if (printed_anything)
- strlcat(nbuf, ", ", nbufsize);
- s = strlen(nbuf);
- snprintf(nbuf+s, nbufsize-s, "%d %s",
- yar, (yar==1) ? "yard" : "yards");
+ strlcat (nbuf, ", ", nbufsize);
+ s = strlen (nbuf);
+ snprintf (nbuf+s, nbufsize-s, "%d %s",
+ yar, (yar==1) ? "yard" : "yards");
printed_anything = True;
}
if (inr >= FOOT) {
ft = inr/FOOT;
inr %= FOOT;
if (printed_anything)
- strlcat(nbuf, ", ", nbufsize);
- s = strlen(nbuf);
- snprintf(nbuf+s, nbufsize-s, "%d %s",
- ft, (ft==1) ? "foot" : "feet");
+ strlcat (nbuf, ", ", nbufsize);
+ s = strlen (nbuf);
+ snprintf (nbuf+s, nbufsize-s, "%d %s",
+ ft, (ft==1) ? "foot" : "feet");
printed_anything = True;
}
if (!printed_anything || inch_frac != 0.0 || inr != 0) {
if (printed_anything)
- strlcat(nbuf, ", ", nbufsize);
- s = strlen(nbuf);
- snprintf(nbuf+s, nbufsize-s, "%.2f inches", inr+inch_frac);
+ strlcat (nbuf, ", ", nbufsize);
+ s = strlen (nbuf);
+ snprintf (nbuf+s, nbufsize-s, "%.2f inches", inr+inch_frac);
}
}
strlcat (nbuf, ")", nbufsize);
}
- return(nbuf);
-}
-
+ return (nbuf);
+}
+
static char xbuf[BUFSIZ];
static char *
-xscale(int x)
+xscale (int x)
{
- if(!xp) {
- scale_init();
- }
- return(nscale(x, xp, xmm, xbuf, sizeof(xbuf)));
+ return (nscale (x, xp, xmm, xbuf, sizeof(xbuf)));
}
static char ybuf[BUFSIZ];
static char *
-yscale(int y)
+yscale (int y)
{
- if(!yp) {
- scale_init();
- }
- return(nscale(y, yp, ymm, ybuf, sizeof(ybuf)));
+ return (nscale (y, yp, ymm, ybuf, sizeof(ybuf)));
}
static char bbuf[BUFSIZ];
static char *
-bscale(int b)
+bscale (int b)
{
- if(!bp) {
- scale_init();
- }
- return(nscale(b, bp, bmm, bbuf, sizeof(bbuf)));
+ return (nscale (b, bp, bmm, bbuf, sizeof(bbuf)));
}
/* end of pixel to inch, metric converter */
-/* This handler is enabled when we are checking
- to see if the -id the user specified is valid. */
-
-/* ARGSUSED */
-static int
-bad_window_handler(Display *disp, XErrorEvent *err)
-{
- char badid[20];
-
- snprintf(badid, sizeof(badid), window_id_format, err->resourceid);
- Fatal_Error("No such window with id %s.", badid);
- exit (1);
- return 0;
-}
-
-
int
-main(int argc, char **argv)
+main (int argc, char **argv)
{
- register int i;
- int tree = 0, stats = 0, bits = 0, events = 0, wm = 0, size = 0, shape = 0;
- int frame = 0, children = 0;
- int pauseatend = 0;
- Window window;
-
- INIT_NAME;
-
-#ifndef NO_I18N
- {
- char *lc;
- lc = setlocale(LC_ALL, "");
- if(!lc)
- fprintf(stderr, "can not set locale properly\n");
- }
+ register int i;
+ int tree = 0, stats = 0, bits = 0, events = 0, wm = 0, size = 0, shape = 0;
+ int frame = 0, children = 0;
+ int pauseatend = 0;
+ int use_root = 0;
+ xcb_window_t window = 0;
+ char *display_name = NULL;
+ const char *window_name = NULL;
+ struct wininfo wininfo;
+ struct wininfo *w = &wininfo;
+
+ program_name = argv[0];
+
+ if (!setlocale (LC_ALL, ""))
+ fprintf (stderr, "%s: can not set locale properly\n", program_name);
+#ifndef _MSC_VER
+ user_encoding = nl_langinfo (CODESET);
#endif
-
- /* Open display, handle command line arguments */
- Setup_Display_And_Screen(&argc, argv);
-
- /* Get window selected on command line, if any */
- window = Select_Window_Args(&argc, argv);
-
- /* Handle our command line arguments */
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-help"))
- usage();
- if (!strcmp(argv[i], "-int")) {
- window_id_format = "%ld";
- continue;
- }
- if (!strcmp(argv[i], "-children")) {
- children = 1;
- continue;
- }
- if (!strcmp(argv[i], "-tree")) {
- tree = 1;
- continue;
- }
- if (!strcmp(argv[i], "-stats")) {
- stats = 1;
- continue;
+ if (user_encoding == NULL)
+ user_encoding = "unknown encoding";
+
+ memset (w, 0, sizeof(struct wininfo));
+
+ /* Handle our command line arguments */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp (argv[i], "-help"))
+ usage ();
+ if (!strcmp (argv[i], "-display") || !strcmp (argv[i], "-d")) {
+ if (++i >= argc)
+ Fatal_Error("-display requires argument");
+ display_name = argv[i];
+ continue;
+ }
+ if (!strcmp (argv[i], "-root")) {
+ use_root = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-id")) {
+ if (++i >= argc)
+ Fatal_Error("-id requires argument");
+ window = strtoul(argv[i], NULL, 0);
+ continue;
+ }
+ if (!strcmp (argv[i], "-name")) {
+ if (++i >= argc)
+ Fatal_Error("-name requires argument");
+ window_name = argv[i];
+ continue;
+ }
+ if (!strcmp (argv[i], "-int")) {
+ window_id_format = "%ld";
+ continue;
+ }
+ if (!strcmp (argv[i], "-children")) {
+ children = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-tree")) {
+ tree = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-stats")) {
+ stats = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-bits")) {
+ bits = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-events")) {
+ events = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-wm")) {
+ wm = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-frame")) {
+ frame = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-size")) {
+ size = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-shape")) {
+ shape = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-english")) {
+ english = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-metric")) {
+ metric = 1;
+ continue;
+ }
+ if (!strcmp (argv[i], "-all")) {
+ tree = stats = bits = events = wm = size = shape = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-pause")) {
+ pauseatend = 1;
+ continue;
+ }
+ usage ();
}
- if (!strcmp(argv[i], "-bits")) {
- bits = 1;
- continue;
+
+ Setup_Display_And_Screen (display_name, &dpy, &screen);
+
+ /* preload atoms we may need later */
+ Intern_Atom (dpy, "_NET_WM_NAME");
+ Intern_Atom (dpy, "UTF8_STRING");
+ if (wm) {
+ Intern_Atom (dpy, "_NET_WM_DESKTOP");
+ Intern_Atom (dpy, "_NET_WM_WINDOW_TYPE");
+ Intern_Atom (dpy, "_NET_WM_STATE");
+ Intern_Atom (dpy, "_NET_WM_PID");
+ Intern_Atom (dpy, "_NET_FRAME_EXTENTS");
}
- if (!strcmp(argv[i], "-events")) {
- events = 1;
- continue;
+ /* initialize scaling data */
+ scale_init(screen);
+
+ if (use_root)
+ window = screen->root;
+ else if (window_name) {
+ window = Window_With_Name (dpy, screen->root, window_name);
+ if (!window)
+ Fatal_Error ("No window with name \"%s\" exists!", window_name);
}
- if (!strcmp(argv[i], "-wm")) {
- wm = 1;
- continue;
+
+ /* If no window selected on command line, let user pick one the hard way */
+ if (!window) {
+ printf ("\n"
+ "xwininfo: Please select the window about which you\n"
+ " would like information by clicking the\n"
+ " mouse in that window.\n");
+ Intern_Atom (dpy, "_NET_VIRTUAL_ROOTS");
+ Intern_Atom (dpy, "WM_STATE");
+ window = Select_Window (dpy, screen, !frame);
}
- if (!strcmp(argv[i], "-frame")) {
- frame = 1;
- continue;
+
+ /*
+ * Do the actual displaying as per parameters
+ */
+ if (!(children || tree || bits || events || wm || size))
+ stats = 1;
+
+ /*
+ * make sure that the window is valid
+ */
+ {
+ xcb_get_geometry_cookie_t gg_cookie =
+ xcb_get_geometry (dpy, window);
+
+ w->geometry = xcb_get_geometry_reply(dpy, gg_cookie, &err);
+
+ if (!w->geometry) {
+ char badid[20];
+
+ if (err)
+ Print_X_Error (dpy, err);
+
+ snprintf (badid, sizeof(badid), window_id_format, window);
+ Fatal_Error ("No such window with id %s.", badid);
+ }
}
- if (!strcmp(argv[i], "-size")) {
- size = 1;
- continue;
+
+ /* Send requests to prefetch data we'll need */
+ w->window = window;
+ w->net_wm_name_cookie = get_net_wm_name (dpy, window);
+ w->wm_name_cookie = xcb_get_wm_name (dpy, window);
+ if (children || tree)
+ w->tree_cookie = xcb_query_tree (dpy, window);
+ if (stats) {
+ w->trans_coords_cookie =
+ xcb_translate_coordinates (dpy, window, w->geometry->root,
+ -(w->geometry->border_width),
+ -(w->geometry->border_width));
}
- if (!strcmp(argv[i], "-shape")) {
- shape = 1;
- continue;
+ if (stats || bits || events)
+ w->attr_cookie = xcb_get_window_attributes (dpy, window);
+ if (stats || size)
+ w->normal_hints_cookie = xcb_get_wm_normal_hints (dpy, window);
+ if (wm) {
+ w->hints_cookie = xcb_get_wm_hints(dpy, window);
+
+ atom_net_wm_desktop = Get_Atom (dpy, "_NET_WM_DESKTOP");
+ if (atom_net_wm_desktop) {
+ w->wm_desktop_cookie = xcb_get_property
+ (dpy, False, window, atom_net_wm_desktop,
+ XCB_ATOM_CARDINAL, 0, 4);
+ }
+
+ atom_net_wm_window_type = Get_Atom (dpy, "_NET_WM_WINDOW_TYPE");
+ if (atom_net_wm_window_type) {
+ w->wm_window_type_cookie = xcb_get_property
+ (dpy, False, window, atom_net_wm_window_type,
+ XCB_ATOM_ATOM, 0, BUFSIZ);
+ }
+
+ atom_net_wm_state = Get_Atom (dpy, "_NET_WM_STATE");
+ if (atom_net_wm_state) {
+ w->wm_state_cookie = xcb_get_property
+ (dpy, False, window, atom_net_wm_state,
+ XCB_ATOM_ATOM, 0, BUFSIZ);
+ }
+
+ atom_net_wm_pid = Get_Atom (dpy, "_NET_WM_PID");
+ if (atom_net_wm_pid) {
+ w->wm_pid_cookie = xcb_get_property
+ (dpy, False, window, atom_net_wm_pid,
+ XCB_ATOM_CARDINAL, 0, BUFSIZ);
+ w->wm_client_machine_cookie =
+ GET_TEXT_PROPERTY(dpy, window, XCB_ATOM_WM_CLIENT_MACHINE);
+ }
+
+ atom_net_frame_extents = Get_Atom (dpy, "_NET_FRAME_EXTENTS");
+ if (atom_net_frame_extents) {
+ w->frame_extents_cookie = xcb_get_property
+ (dpy, False, window, atom_net_frame_extents,
+ XCB_ATOM_CARDINAL, 0, 4 * 4);
+ }
}
- if (!strcmp(argv[i], "-english")) {
- english = 1;
- continue;
+ if (size)
+ w->zoom_cookie = xcb_get_wm_size_hints (dpy, window,
+ XCB_ATOM_WM_ZOOM_HINTS);
+ xcb_flush (dpy);
+
+ printf ("\nxwininfo: Window id: ");
+ Display_Window_Id (w, True);
+ if (children || tree)
+ Display_Tree_Info (w, tree);
+ if (stats)
+ Display_Stats_Info (w);
+ if (bits)
+ Display_Bits_Info (w);
+ if (events)
+ Display_Events_Info (w);
+ if (wm)
+ Display_WM_Info (w);
+ if (size)
+ Display_Size_Hints (w);
+ if (shape)
+ Display_Window_Shape (window);
+ printf ("\n");
+ if (pauseatend) getchar();
+
+ wininfo_wipe (w);
+ xcb_disconnect (dpy);
+#ifdef HAVE_ICONV
+ if (iconv_from_utf8 && (iconv_from_utf8 != (iconv_t) -1)) {
+ iconv_close (iconv_from_utf8);
}
- if (!strcmp(argv[i], "-metric")) {
- metric = 1;
- continue;
+#endif
+ exit (0);
+}
+
+/* Ensure win_attributes field is filled in */
+static xcb_get_window_attributes_reply_t *
+fetch_win_attributes (struct wininfo *w)
+{
+ if (!w->win_attributes) {
+ w->win_attributes =
+ xcb_get_window_attributes_reply (dpy, w->attr_cookie, &err);
+
+ if (!w->win_attributes) {
+ Print_X_Error (dpy, err);
+ Fatal_Error ("Can't get window attributes.");
+ }
}
- if (!strcmp(argv[i], "-all")) {
- tree = stats = bits = events = wm = size = shape = 1;
- continue;
+ return w->win_attributes;
+}
+
+#ifndef USE_XCB_ICCCM
+static Bool
+wm_size_hints_reply (xcb_connection_t *dpy, xcb_get_property_cookie_t cookie,
+ wm_size_hints_t *hints_return, xcb_generic_error_t **err)
+{
+ xcb_get_property_reply_t *prop = xcb_get_property_reply (dpy, cookie, err);
+ int length;
+
+ if (!prop || (prop->type != XCB_ATOM_WM_SIZE_HINTS) ||
+ (prop->format != 32)) {
+ free (prop);
+ return False;
}
- if (!strcmp(argv[i], "-pause")) {
- pauseatend = 1;
- continue;
+
+ memset (hints_return, 0, sizeof(wm_size_hints_t));
+
+ length = xcb_get_property_value_length(prop);
+ if (length > sizeof(wm_size_hints_t))
+ length = sizeof(wm_size_hints_t);
+ memcpy (hints_return, xcb_get_property_value (prop), length);
+
+ free (prop);
+ return True;
+}
+
+#define xcb_get_wm_normal_hints_reply wm_size_hints_reply
+#define xcb_get_wm_size_hints_reply wm_size_hints_reply
+#endif
+
+
+
+/* Ensure normal_hints field is filled in */
+static xcb_size_hints_t *
+fetch_normal_hints (struct wininfo *w, xcb_size_hints_t *hints_return)
+{
+ xcb_size_hints_t hints;
+
+ if (!w->normal_hints) {
+ if (xcb_get_wm_normal_hints_reply (dpy, w->normal_hints_cookie,
+ &hints, NULL)) {
+ w->normal_hints = malloc (sizeof(xcb_size_hints_t));
+ if (w->normal_hints)
+ memcpy(w->normal_hints, &hints, sizeof(xcb_size_hints_t));
+ }
}
- usage();
- }
-
- /* If no window selected on command line, let user pick one the hard way */
- if (!window) {
- printf("\n");
- printf("xwininfo: Please select the window about which you\n");
- printf(" would like information by clicking the\n");
- printf(" mouse in that window.\n");
- window = Select_Window(dpy, !frame);
- }
-
- /*
- * Do the actual displaying as per parameters
- */
- if (!(children || tree || bits || events || wm || size))
- stats = 1;
-
- /*
- * make sure that the window is valid
- */
- {
- Window root;
- int x, y;
- unsigned width, height, bw, depth;
- XErrorHandler old_handler;
-
- old_handler = XSetErrorHandler(bad_window_handler);
- XGetGeometry (dpy, window, &root, &x, &y, &width, &height, &bw, &depth);
- XSync (dpy, False);
- (void) XSetErrorHandler(old_handler);
- }
-
- printf("\nxwininfo: Window id: ");
- Display_Window_Id(window, True);
- if (children || tree)
- Display_Tree_Info(window, tree);
- if (stats)
- Display_Stats_Info(window);
- if (bits)
- Display_Bits_Info(window);
- if (events)
- Display_Events_Info(window);
- if (wm)
- Display_WM_Info(window);
- if (size)
- Display_Size_Hints(window);
- if (shape)
- Display_Window_Shape(window);
- printf("\n");
- if (pauseatend) getchar();
- exit(0);
+ if (hints_return && w->normal_hints)
+ memcpy(hints_return, w->normal_hints, sizeof(xcb_size_hints_t));
+ return w->normal_hints;
}
@@ -445,85 +758,115 @@ main(int argc, char **argv)
static char _lookup_buffer[100];
static const char *
-LookupL(long code, const binding *table)
+LookupL (long code, const binding *table)
{
- const char *name;
-
- snprintf(_lookup_buffer, sizeof(_lookup_buffer),
- "unknown (code = %ld. = 0x%lx)", code, code);
- name = _lookup_buffer;
+ const char *name = NULL;
- while (table->name) {
- if (table->code == code) {
- name = table->name;
- break;
- }
- table++;
+ while (table->name) {
+ if (table->code == code) {
+ name = table->name;
+ break;
}
+ table++;
+ }
+
+ if (name == NULL) {
+ snprintf (_lookup_buffer, sizeof(_lookup_buffer),
+ "unknown (code = %ld. = 0x%lx)", code, code);
+ name = _lookup_buffer;
+ }
- return(name);
+ return (name);
}
static const char *
-Lookup(int code, const binding *table)
+Lookup (int code, const binding *table)
{
- return LookupL((long)code, table);
+ return LookupL ((long)code, table);
}
/*
* Routine to display a window id in dec/hex with name if window has one
+ *
+ * Requires wininfo members initialized: window, wm_name_cookie
*/
static void
-Display_Window_Id(Window window, Bool newline_wanted)
+Display_Window_Id (struct wininfo *w, Bool newline_wanted)
{
-#ifdef NO_I18N
- char *win_name;
-#else
- XTextProperty tp;
+#ifdef USE_XCB_ICCCM
+ xcb_get_text_property_reply_t wmn_reply;
#endif
-
- printf(window_id_format, window); /* print id # in hex/dec */
+ xcb_get_property_reply_t *prop;
+ uint8_t got_reply = False;
+ const char *wm_name = NULL;
+ unsigned int wm_name_len = 0;
+ xcb_atom_t wm_name_encoding = XCB_NONE;
- if (!window) {
- printf(" (none)");
+ printf (window_id_format, w->window); /* print id # in hex/dec */
+
+ if (!w->window) {
+ printf (" (none)");
} else {
- if (window == RootWindow(dpy, screen)) {
- printf(" (the root window)");
+ if (w->window == screen->root) {
+ printf (" (the root window)");
}
-#ifdef NO_I18N
- if (!XFetchName(dpy, window, &win_name)) { /* Get window name if any */
- printf(" (has no name)");
- } else if (win_name) {
- printf(" \"%s\"", win_name);
- XFree(win_name);
+ /* Get window name if any */
+ prop = xcb_get_property_reply (dpy, w->net_wm_name_cookie, NULL);
+ if (prop && (prop->type != XCB_NONE)) {
+ wm_name = xcb_get_property_value (prop);
+ wm_name_len = xcb_get_property_value_length (prop);
+ wm_name_encoding = prop->type;
+ got_reply = True;
}
+
+ if (!got_reply) { /* No _NET_WM_NAME, check WM_NAME */
+#ifdef USE_XCB_ICCCM
+ got_reply = xcb_get_wm_name_reply (dpy, w->wm_name_cookie,
+ &wmn_reply, NULL);
+ if (got_reply) {
+ wm_name = wmn_reply.name;
+ wm_name_len = wmn_reply.name_len;
+ wm_name_encoding = wmn_reply.encoding;
+ }
#else
- if (!XGetWMName(dpy, window, &tp)) { /* Get window name if any */
- printf(" (has no name)");
- } else if (tp.nitems > 0) {
- printf(" \"");
- {
- int count = 0, i, ret;
- char **list = NULL;
- ret = XmbTextPropertyToTextList(dpy, &tp, &list, &count);
- if((ret == Success || ret > 0) && list != NULL){
- for(i=0; i<count; i++)
- printf("%s", list[i]);
- XFreeStringList(list);
- } else {
- printf("%s", tp.value);
- }
- }
- printf("\"");
+ prop = xcb_get_property_reply (dpy, w->wm_name_cookie, NULL);
+ if (prop && (prop->type != XCB_NONE)) {
+ wm_name = xcb_get_property_value (prop);
+ wm_name_len = xcb_get_property_value_length (prop);
+ wm_name_encoding = prop->type;
+ got_reply = True;
+ }
+#endif
}
+ if (!got_reply || wm_name_len == 0) {
+ printf (" (has no name)");
+ } else {
+ if (wm_name_encoding == XCB_ATOM_STRING) {
+ printf (" \"%.*s\"", wm_name_len, wm_name);
+ } else if (wm_name_encoding == atom_utf8_string) {
+ print_utf8 (" \"", (char *) wm_name, wm_name_len, "\"");
+ } else {
+ /* Encodings we don't support, including COMPOUND_TEXT */
+ const char *enc_name = Get_Atom_Name (dpy, wm_name_encoding);
+ if (enc_name) {
+ printf (" (name in unsupported encoding %s)", enc_name);
+ } else {
+ printf (" (name in unsupported encoding ATOM 0x%x)",
+ wm_name_encoding);
+ }
+ }
+ }
+#ifdef USE_XCB_ICCCM
+ if (got_reply)
+ xcb_get_text_property_reply_wipe (&wmn_reply);
+#else
+ free (prop);
#endif
- else
- printf(" (has no name)");
}
if (newline_wanted)
- printf("\n");
+ printf ("\n");
return;
}
@@ -533,221 +876,255 @@ Display_Window_Id(Window window, Bool newline_wanted)
* Display Stats on window
*/
static const binding _window_classes[] = {
- { InputOutput, "InputOutput" },
- { InputOnly, "InputOnly" },
+ { XCB_WINDOW_CLASS_INPUT_OUTPUT, "InputOutput" },
+ { XCB_WINDOW_CLASS_INPUT_ONLY, "InputOnly" },
{ 0, NULL } };
static const binding _map_states[] = {
- { IsUnmapped, "IsUnMapped" },
- { IsUnviewable, "IsUnviewable" },
- { IsViewable, "IsViewable" },
+ { XCB_MAP_STATE_UNMAPPED, "IsUnMapped" },
+ { XCB_MAP_STATE_UNVIEWABLE, "IsUnviewable" },
+ { XCB_MAP_STATE_VIEWABLE, "IsViewable" },
{ 0, NULL } };
static const binding _backing_store_states[] = {
- { NotUseful, "NotUseful" },
- { WhenMapped, "WhenMapped" },
- { Always, "Always" },
+ { XCB_BACKING_STORE_NOT_USEFUL, "NotUseful" },
+ { XCB_BACKING_STORE_WHEN_MAPPED,"WhenMapped" },
+ { XCB_BACKING_STORE_ALWAYS, "Always" },
{ 0, NULL } };
static const binding _bit_gravity_states[] = {
- { ForgetGravity, "ForgetGravity" },
- { NorthWestGravity, "NorthWestGravity" },
- { NorthGravity, "NorthGravity" },
- { NorthEastGravity, "NorthEastGravity" },
- { WestGravity, "WestGravity" },
- { CenterGravity, "CenterGravity" },
- { EastGravity, "EastGravity" },
- { SouthWestGravity, "SouthWestGravity" },
- { SouthGravity, "SouthGravity" },
- { SouthEastGravity, "SouthEastGravity" },
- { StaticGravity, "StaticGravity" },
+ { XCB_GRAVITY_BIT_FORGET, "ForgetGravity" },
+ { XCB_GRAVITY_NORTH_WEST, "NorthWestGravity" },
+ { XCB_GRAVITY_NORTH, "NorthGravity" },
+ { XCB_GRAVITY_NORTH_EAST, "NorthEastGravity" },
+ { XCB_GRAVITY_WEST, "WestGravity" },
+ { XCB_GRAVITY_CENTER, "CenterGravity" },
+ { XCB_GRAVITY_EAST, "EastGravity" },
+ { XCB_GRAVITY_SOUTH_WEST, "SouthWestGravity" },
+ { XCB_GRAVITY_SOUTH, "SouthGravity" },
+ { XCB_GRAVITY_SOUTH_EAST, "SouthEastGravity" },
+ { XCB_GRAVITY_STATIC, "StaticGravity" },
{ 0, NULL }};
static const binding _window_gravity_states[] = {
- { UnmapGravity, "UnmapGravity" },
- { NorthWestGravity, "NorthWestGravity" },
- { NorthGravity, "NorthGravity" },
- { NorthEastGravity, "NorthEastGravity" },
- { WestGravity, "WestGravity" },
- { CenterGravity, "CenterGravity" },
- { EastGravity, "EastGravity" },
- { SouthWestGravity, "SouthWestGravity" },
- { SouthGravity, "SouthGravity" },
- { SouthEastGravity, "SouthEastGravity" },
- { StaticGravity, "StaticGravity" },
+ { XCB_GRAVITY_WIN_UNMAP, "UnmapGravity" },
+ { XCB_GRAVITY_NORTH_WEST, "NorthWestGravity" },
+ { XCB_GRAVITY_NORTH, "NorthGravity" },
+ { XCB_GRAVITY_NORTH_EAST, "NorthEastGravity" },
+ { XCB_GRAVITY_WEST, "WestGravity" },
+ { XCB_GRAVITY_CENTER, "CenterGravity" },
+ { XCB_GRAVITY_EAST, "EastGravity" },
+ { XCB_GRAVITY_SOUTH_WEST, "SouthWestGravity" },
+ { XCB_GRAVITY_SOUTH, "SouthGravity" },
+ { XCB_GRAVITY_SOUTH_EAST, "SouthEastGravity" },
+ { XCB_GRAVITY_STATIC, "StaticGravity" },
{ 0, NULL }};
static const binding _visual_classes[] = {
- { StaticGray, "StaticGray" },
- { GrayScale, "GrayScale" },
- { StaticColor, "StaticColor" },
- { PseudoColor, "PseudoColor" },
- { TrueColor, "TrueColor" },
- { DirectColor, "DirectColor" },
+ { XCB_VISUAL_CLASS_STATIC_GRAY, "StaticGray" },
+ { XCB_VISUAL_CLASS_GRAY_SCALE, "GrayScale" },
+ { XCB_VISUAL_CLASS_STATIC_COLOR,"StaticColor" },
+ { XCB_VISUAL_CLASS_PSEUDO_COLOR,"PseudoColor" },
+ { XCB_VISUAL_CLASS_TRUE_COLOR, "TrueColor" },
+ { XCB_VISUAL_CLASS_DIRECT_COLOR,"DirectColor" },
{ 0, NULL }};
+/*
+ * Requires wininfo members initialized:
+ * window, geometry, attr_cookie, trans_coords_cookie, normal_hints_cookie
+ */
static void
-Display_Stats_Info(Window window)
+Display_Stats_Info (struct wininfo *w)
{
- XWindowAttributes win_attributes;
- XVisualInfo vistemplate, *vinfo;
- XSizeHints hints;
- int dw = DisplayWidth (dpy, screen), dh = DisplayHeight (dpy, screen);
- int rx, ry, xright, ybelow;
- int showright = 0, showbelow = 0;
- Status status;
- Window wmframe;
- int junk;
- long longjunk;
- Window junkwin;
-
- if (!XGetWindowAttributes(dpy, window, &win_attributes))
- Fatal_Error("Can't get window attributes.");
- vistemplate.visualid = XVisualIDFromVisual(win_attributes.visual);
- vinfo = XGetVisualInfo(dpy, VisualIDMask, &vistemplate, &junk);
-
- (void) XTranslateCoordinates (dpy, window, win_attributes.root,
- -win_attributes.border_width,
- -win_attributes.border_width,
- &rx, &ry, &junkwin);
-
- xright = (dw - rx - win_attributes.border_width * 2 -
- win_attributes.width);
- ybelow = (dh - ry - win_attributes.border_width * 2 -
- win_attributes.height);
-
- printf("\n");
- printf(" Absolute upper-left X: %s\n", xscale(rx));
- printf(" Absolute upper-left Y: %s\n", yscale(ry));
- printf(" Relative upper-left X: %s\n", xscale(win_attributes.x));
- printf(" Relative upper-left Y: %s\n", yscale(win_attributes.y));
- printf(" Width: %s\n", xscale(win_attributes.width));
- printf(" Height: %s\n", yscale(win_attributes.height));
- printf(" Depth: %d\n", win_attributes.depth);
- printf(" Visual: 0x%lx\n", vinfo->visualid);
- printf(" Visual Class: %s\n", Lookup(vinfo->class, _visual_classes));
- printf(" Border width: %s\n", bscale(win_attributes.border_width));
- printf(" Class: %s\n",
- Lookup(win_attributes.class, _window_classes));
- printf(" Colormap: 0x%lx (%sinstalled)\n",
- win_attributes.colormap, win_attributes.map_installed ? "" : "not ");
- printf(" Bit Gravity State: %s\n",
- Lookup(win_attributes.bit_gravity, _bit_gravity_states));
- printf(" Window Gravity State: %s\n",
- Lookup(win_attributes.win_gravity, _window_gravity_states));
- printf(" Backing Store State: %s\n",
- Lookup(win_attributes.backing_store, _backing_store_states));
- printf(" Save Under State: %s\n",
- win_attributes.save_under ? "yes" : "no");
- printf(" Map State: %s\n",
- Lookup(win_attributes.map_state, _map_states));
- printf(" Override Redirect State: %s\n",
- win_attributes.override_redirect ? "yes" : "no");
- printf(" Corners: +%d+%d -%d+%d -%d-%d +%d-%d\n",
- rx, ry, xright, ry, xright, ybelow, rx, ybelow);
-
- XFree(vinfo);
-
- /*
- * compute geometry string that would recreate window
- */
- printf(" -geometry ");
-
- /* compute size in appropriate units */
- status = XGetWMNormalHints(dpy, window, &hints, &longjunk);
- if (status && hints.flags & PResizeInc &&
- hints.width_inc != 0 && hints.height_inc != 0) {
- if (hints.flags & (PBaseSize|PMinSize)) {
- if (hints.flags & PBaseSize) {
- win_attributes.width -= hints.base_width;
- win_attributes.height -= hints.base_height;
- } else {
- /* ICCCM says MinSize is default for BaseSize */
- win_attributes.width -= hints.min_width;
- win_attributes.height -= hints.min_height;
- }
- }
- printf("%dx%d", win_attributes.width/hints.width_inc,
- win_attributes.height/hints.height_inc);
- } else
- printf("%dx%d", win_attributes.width, win_attributes.height);
-
- if (!(hints.flags&PWinGravity))
- hints.win_gravity = NorthWestGravity; /* per ICCCM */
- /* find our window manager frame, if any */
- wmframe = window;
- while (True) {
- Window root, parent;
- Window *childlist;
- unsigned int ujunk;
-
- status = XQueryTree(dpy, wmframe, &root, &parent, &childlist, &ujunk);
- if (parent == root || !parent || !status)
- break;
- wmframe = parent;
- if (status && childlist)
- XFree((char *)childlist);
- }
- if (wmframe != window) {
- /* WM reparented, so find edges of the frame */
- /* Only works for ICCCM-compliant WMs, and then only if the
- window has corner gravity. We would need to know the original width
- of the window to correctly handle the other gravities. */
-
- XWindowAttributes frame_attr;
-
- if (!XGetWindowAttributes(dpy, wmframe, &frame_attr))
- Fatal_Error("Can't get frame attributes.");
- switch (hints.win_gravity) {
- case NorthWestGravity: case SouthWestGravity:
- case NorthEastGravity: case SouthEastGravity:
- case WestGravity:
- rx = frame_attr.x;
- }
- switch (hints.win_gravity) {
- case NorthWestGravity: case SouthWestGravity:
- case NorthEastGravity: case SouthEastGravity:
- case EastGravity:
- xright = dw - frame_attr.x - frame_attr.width -
- 2*frame_attr.border_width;
- }
- switch (hints.win_gravity) {
- case NorthWestGravity: case SouthWestGravity:
- case NorthEastGravity: case SouthEastGravity:
- case NorthGravity:
- ry = frame_attr.y;
- }
- switch (hints.win_gravity) {
- case NorthWestGravity: case SouthWestGravity:
- case NorthEastGravity: case SouthEastGravity:
- case SouthGravity:
- ybelow = dh - frame_attr.y - frame_attr.height -
- 2*frame_attr.border_width;
- }
- }
- /* If edge gravity, offer a corner on that edge (because the application
- programmer cares about that edge), otherwise offer upper left unless
- some other corner is close to an edge of the screen.
- (For corner gravity, assume gravity was set by XWMGeometry.
- For CenterGravity, it doesn't matter.) */
- if (hints.win_gravity == EastGravity ||
- (abs(xright) <= 100 && abs(xright) < abs(rx)
- && hints.win_gravity != WestGravity))
- showright = 1;
- if (hints.win_gravity == SouthGravity ||
- (abs(ybelow) <= 100 && abs(ybelow) < abs(ry)
- && hints.win_gravity != NorthGravity))
- showbelow = 1;
-
- if (showright)
- printf("-%d", xright);
- else
- printf("+%d", rx);
- if (showbelow)
- printf("-%d", ybelow);
- else
- printf("+%d", ry);
- printf("\n");
+ xcb_translate_coordinates_reply_t *trans_coords;
+ xcb_get_window_attributes_reply_t *win_attributes;
+ xcb_size_hints_t hints;
+
+ int dw = screen->width_in_pixels, dh = screen->height_in_pixels;
+ int rx, ry, xright, ybelow;
+ int showright = 0, showbelow = 0;
+ xcb_window_t wmframe, parent;
+
+ trans_coords =
+ xcb_translate_coordinates_reply (dpy, w->trans_coords_cookie, NULL);
+ if (!trans_coords)
+ Fatal_Error ("Can't get translated coordinates.");
+
+ rx = trans_coords->dst_x;
+ ry = trans_coords->dst_y;
+ free (trans_coords);
+
+ xright = (dw - rx - w->geometry->border_width * 2 -
+ w->geometry->width);
+ ybelow = (dh - ry - w->geometry->border_width * 2 -
+ w->geometry->height);
+
+
+ printf ("\n");
+ printf (" Absolute upper-left X: %s\n", xscale (rx));
+ printf (" Absolute upper-left Y: %s\n", yscale (ry));
+ printf (" Relative upper-left X: %s\n", xscale (w->geometry->x));
+ printf (" Relative upper-left Y: %s\n", yscale (w->geometry->y));
+ printf (" Width: %s\n", xscale (w->geometry->width));
+ printf (" Height: %s\n", yscale (w->geometry->height));
+ printf (" Depth: %d\n", w->geometry->depth);
+
+ win_attributes = fetch_win_attributes (w);
+
+ printf (" Visual: 0x%lx\n", (unsigned long) win_attributes->visual);
+ if (screen)
+ {
+ xcb_depth_iterator_t depth_iter;
+ xcb_visualtype_t *visual_type = NULL;
+
+ depth_iter = xcb_screen_allowed_depths_iterator (screen);
+ for (; depth_iter.rem; xcb_depth_next (&depth_iter)) {
+ xcb_visualtype_iterator_t visual_iter;
+
+ visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
+ for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) {
+ if (screen->root_visual == visual_iter.data->visual_id) {
+ visual_type = visual_iter.data;
+ break;
+ }
+ }
+ }
+ if (visual_type)
+ printf (" Visual Class: %s\n", Lookup (visual_type->_class,
+ _visual_classes));
+ }
+
+ printf (" Border width: %s\n", bscale (w->geometry->border_width));
+ printf (" Class: %s\n",
+ Lookup (win_attributes->_class, _window_classes));
+ printf (" Colormap: 0x%lx (%sinstalled)\n",
+ (unsigned long) win_attributes->colormap,
+ win_attributes->map_is_installed ? "" : "not ");
+ printf (" Bit Gravity State: %s\n",
+ Lookup (win_attributes->bit_gravity, _bit_gravity_states));
+ printf (" Window Gravity State: %s\n",
+ Lookup (win_attributes->win_gravity, _window_gravity_states));
+ printf (" Backing Store State: %s\n",
+ Lookup (win_attributes->backing_store, _backing_store_states));
+ printf (" Save Under State: %s\n",
+ win_attributes->save_under ? "yes" : "no");
+ printf (" Map State: %s\n",
+ Lookup (win_attributes->map_state, _map_states));
+ printf (" Override Redirect State: %s\n",
+ win_attributes->override_redirect ? "yes" : "no");
+ printf (" Corners: +%d+%d -%d+%d -%d-%d +%d-%d\n",
+ rx, ry, xright, ry, xright, ybelow, rx, ybelow);
+
+ /*
+ * compute geometry string that would recreate window
+ */
+ printf (" -geometry ");
+
+ /* compute size in appropriate units */
+ if (!fetch_normal_hints (w, &hints))
+ hints.flags = 0;
+
+ if ((hints.flags & XCB_SIZE_HINT_P_RESIZE_INC) &&
+ (hints.width_inc != 0) && (hints.height_inc != 0)) {
+ if (hints.flags & (XCB_SIZE_HINT_BASE_SIZE|XCB_SIZE_HINT_P_MIN_SIZE)) {
+ if (hints.flags & XCB_SIZE_HINT_BASE_SIZE) {
+ w->geometry->width -= hints.base_width;
+ w->geometry->height -= hints.base_height;
+ } else {
+ /* ICCCM says MinSize is default for BaseSize */
+ w->geometry->width -= hints.min_width;
+ w->geometry->height -= hints.min_height;
+ }
+ }
+ printf ("%dx%d", w->geometry->width/hints.width_inc,
+ w->geometry->height/hints.height_inc);
+ } else
+ printf ("%dx%d", w->geometry->width, w->geometry->height);
+
+ if (!(hints.flags & XCB_SIZE_HINT_P_WIN_GRAVITY))
+ hints.win_gravity = XCB_GRAVITY_NORTH_WEST; /* per ICCCM */
+ /* find our window manager frame, if any */
+ for (wmframe = parent = w->window; parent != 0 ; wmframe = parent) {
+ xcb_query_tree_cookie_t qt_cookie;
+ xcb_query_tree_reply_t *tree;
+
+ qt_cookie = xcb_query_tree (dpy, wmframe);
+ tree = xcb_query_tree_reply (dpy, qt_cookie, &err);
+ if (!tree) {
+ Print_X_Error (dpy, err);
+ Fatal_Error ("Can't query window tree.");
+ }
+ parent = tree->parent;
+ free (tree);
+ if (parent == w->geometry->root || !parent)
+ break;
+ }
+ if (wmframe != w->window) {
+ /* WM reparented, so find edges of the frame */
+ /* Only works for ICCCM-compliant WMs, and then only if the
+ window has corner gravity. We would need to know the original width
+ of the window to correctly handle the other gravities. */
+ xcb_get_geometry_cookie_t geom_cookie;
+ xcb_get_geometry_reply_t *frame_geometry;
+
+ geom_cookie = xcb_get_geometry (dpy, wmframe);
+ frame_geometry = xcb_get_geometry_reply (dpy, geom_cookie, &err);
+
+ if (!frame_geometry) {
+ Print_X_Error (dpy, err);
+ Fatal_Error ("Can't get frame geometry.");
+ }
+ switch (hints.win_gravity) {
+ case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST:
+ case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST:
+ case XCB_GRAVITY_WEST:
+ rx = frame_geometry->x;
+ }
+ switch (hints.win_gravity) {
+ case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST:
+ case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST:
+ case XCB_GRAVITY_EAST:
+ xright = dw - frame_geometry->x - frame_geometry->width -
+ (2 * frame_geometry->border_width);
+ }
+ switch (hints.win_gravity) {
+ case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST:
+ case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST:
+ case XCB_GRAVITY_NORTH:
+ ry = frame_geometry->y;
+ }
+ switch (hints.win_gravity) {
+ case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST:
+ case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST:
+ case XCB_GRAVITY_SOUTH:
+ ybelow = dh - frame_geometry->y - frame_geometry->height -
+ (2 * frame_geometry->border_width);
+ }
+ free (frame_geometry);
+ }
+ /* If edge gravity, offer a corner on that edge (because the application
+ programmer cares about that edge), otherwise offer upper left unless
+ some other corner is close to an edge of the screen.
+ (For corner gravity, assume gravity was set by XWMGeometry.
+ For CenterGravity, it doesn't matter.) */
+ if (hints.win_gravity == XCB_GRAVITY_EAST ||
+ (abs (xright) <= 100 && abs (xright) < abs (rx)
+ && hints.win_gravity != XCB_GRAVITY_WEST))
+ showright = 1;
+ if (hints.win_gravity == XCB_GRAVITY_SOUTH ||
+ (abs (ybelow) <= 100 && abs (ybelow) < abs (ry)
+ && hints.win_gravity != XCB_GRAVITY_NORTH))
+ showbelow = 1;
+
+ if (showright)
+ printf ("-%d", xright);
+ else
+ printf ("+%d", rx);
+ if (showbelow)
+ printf ("-%d", ybelow);
+ else
+ printf ("+%d", ry);
+ printf ("\n");
}
@@ -755,24 +1132,25 @@ Display_Stats_Info(Window window)
* Display bits info:
*/
static const binding _gravities[] = {
- { UnmapGravity, "UnMapGravity" }, /* WARNING: both of these have*/
- { ForgetGravity, "ForgetGravity" }, /* the same value - see code */
- { NorthWestGravity, "NorthWestGravity" },
- { NorthGravity, "NorthGravity" },
- { NorthEastGravity, "NorthEastGravity" },
- { WestGravity, "WestGravity" },
- { CenterGravity, "CenterGravity" },
- { EastGravity, "EastGravity" },
- { SouthWestGravity, "SouthWestGravity" },
- { SouthGravity, "SouthGravity" },
- { SouthEastGravity, "SouthEastGravity" },
- { StaticGravity, "StaticGravity" },
+ /* WARNING: the first two of these have the same value - see code */
+ { XCB_GRAVITY_WIN_UNMAP, "UnMapGravity" },
+ { XCB_GRAVITY_BIT_FORGET, "ForgetGravity" },
+ { XCB_GRAVITY_NORTH_WEST, "NorthWestGravity" },
+ { XCB_GRAVITY_NORTH, "NorthGravity" },
+ { XCB_GRAVITY_NORTH_EAST, "NorthEastGravity" },
+ { XCB_GRAVITY_WEST, "WestGravity" },
+ { XCB_GRAVITY_CENTER, "CenterGravity" },
+ { XCB_GRAVITY_EAST, "EastGravity" },
+ { XCB_GRAVITY_SOUTH_WEST, "SouthWestGravity" },
+ { XCB_GRAVITY_SOUTH, "SouthGravity" },
+ { XCB_GRAVITY_SOUTH_EAST, "SouthEastGravity" },
+ { XCB_GRAVITY_STATIC, "StaticGravity" },
{ 0, NULL } };
static const binding _backing_store_hint[] = {
- { NotUseful, "NotUseful" },
- { WhenMapped, "WhenMapped" },
- { Always, "Always" },
+ { XCB_BACKING_STORE_NOT_USEFUL, "NotUseful" },
+ { XCB_BACKING_STORE_WHEN_MAPPED,"WhenMapped" },
+ { XCB_BACKING_STORE_ALWAYS, "Always" },
{ 0, NULL } };
static const binding _bool[] = {
@@ -780,26 +1158,29 @@ static const binding _bool[] = {
{ 1, "Yes" },
{ 0, NULL } };
+/*
+ * Requires wininfo members initialized:
+ * window, attr_cookie (or win_attributes)
+ */
static void
-Display_Bits_Info(Window window)
+Display_Bits_Info (struct wininfo * w)
{
- XWindowAttributes win_attributes;
-
- if (!XGetWindowAttributes(dpy, window, &win_attributes))
- Fatal_Error("Can't get window attributes.");
-
- printf("\n");
- printf(" Bit gravity: %s\n",
- Lookup(win_attributes.bit_gravity, _gravities+1));
- printf(" Window gravity: %s\n",
- Lookup(win_attributes.win_gravity, _gravities));
- printf(" Backing-store hint: %s\n",
- Lookup(win_attributes.backing_store, _backing_store_hint));
- printf(" Backing-planes to be preserved: 0x%lx\n",
- win_attributes.backing_planes);
- printf(" Backing pixel: %ld\n", win_attributes.backing_pixel);
- printf(" Save-unders: %s\n",
- Lookup(win_attributes.save_under, _bool));
+ xcb_get_window_attributes_reply_t *win_attributes
+ = fetch_win_attributes (w);
+
+ printf ("\n");
+ printf (" Bit gravity: %s\n",
+ Lookup (win_attributes->bit_gravity, _gravities+1));
+ printf (" Window gravity: %s\n",
+ Lookup (win_attributes->win_gravity, _gravities));
+ printf (" Backing-store hint: %s\n",
+ Lookup (win_attributes->backing_store, _backing_store_hint));
+ printf (" Backing-planes to be preserved: 0x%lx\n",
+ (unsigned long) win_attributes->backing_planes);
+ printf (" Backing pixel: %ld\n",
+ (unsigned long) win_attributes->backing_pixel);
+ printf (" Save-unders: %s\n",
+ Lookup (win_attributes->save_under, _bool));
}
@@ -807,65 +1188,66 @@ Display_Bits_Info(Window window)
* Routine to display all events in an event mask
*/
static const binding _event_mask_names[] = {
- { KeyPressMask, "KeyPress" },
- { KeyReleaseMask, "KeyRelease" },
- { ButtonPressMask, "ButtonPress" },
- { ButtonReleaseMask, "ButtonRelease" },
- { EnterWindowMask, "EnterWindow" },
- { LeaveWindowMask, "LeaveWindow" },
- { PointerMotionMask, "PointerMotion" },
- { PointerMotionHintMask, "PointerMotionHint" },
- { Button1MotionMask, "Button1Motion" },
- { Button2MotionMask, "Button2Motion" },
- { Button3MotionMask, "Button3Motion" },
- { Button4MotionMask, "Button4Motion" },
- { Button5MotionMask, "Button5Motion" },
- { ButtonMotionMask, "ButtonMotion" },
- { KeymapStateMask, "KeymapState" },
- { ExposureMask, "Exposure" },
- { VisibilityChangeMask, "VisibilityChange" },
- { StructureNotifyMask, "StructureNotify" },
- { ResizeRedirectMask, "ResizeRedirect" },
- { SubstructureNotifyMask, "SubstructureNotify" },
- { SubstructureRedirectMask, "SubstructureRedirect" },
- { FocusChangeMask, "FocusChange" },
- { PropertyChangeMask, "PropertyChange" },
- { ColormapChangeMask, "ColormapChange" },
- { OwnerGrabButtonMask, "OwnerGrabButton" },
+ { XCB_EVENT_MASK_KEY_PRESS, "KeyPress" },
+ { XCB_EVENT_MASK_KEY_RELEASE, "KeyRelease" },
+ { XCB_EVENT_MASK_BUTTON_PRESS, "ButtonPress" },
+ { XCB_EVENT_MASK_BUTTON_RELEASE, "ButtonRelease" },
+ { XCB_EVENT_MASK_ENTER_WINDOW, "EnterWindow" },
+ { XCB_EVENT_MASK_LEAVE_WINDOW, "LeaveWindow" },
+ { XCB_EVENT_MASK_POINTER_MOTION, "PointerMotion" },
+ { XCB_EVENT_MASK_POINTER_MOTION_HINT, "PointerMotionHint" },
+ { XCB_EVENT_MASK_BUTTON_1_MOTION, "Button1Motion" },
+ { XCB_EVENT_MASK_BUTTON_2_MOTION, "Button2Motion" },
+ { XCB_EVENT_MASK_BUTTON_3_MOTION, "Button3Motion" },
+ { XCB_EVENT_MASK_BUTTON_4_MOTION, "Button4Motion" },
+ { XCB_EVENT_MASK_BUTTON_5_MOTION, "Button5Motion" },
+ { XCB_EVENT_MASK_BUTTON_MOTION, "ButtonMotion" },
+ { XCB_EVENT_MASK_KEYMAP_STATE, "KeymapState" },
+ { XCB_EVENT_MASK_EXPOSURE, "Exposure" },
+ { XCB_EVENT_MASK_VISIBILITY_CHANGE, "VisibilityChange" },
+ { XCB_EVENT_MASK_STRUCTURE_NOTIFY, "StructureNotify" },
+ { XCB_EVENT_MASK_RESIZE_REDIRECT, "ResizeRedirect" },
+ { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, "SubstructureNotify" },
+ { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, "SubstructureRedirect" },
+ { XCB_EVENT_MASK_FOCUS_CHANGE, "FocusChange" },
+ { XCB_EVENT_MASK_PROPERTY_CHANGE, "PropertyChange" },
+ { XCB_EVENT_MASK_COLOR_MAP_CHANGE, "ColormapChange" },
+ { XCB_EVENT_MASK_OWNER_GRAB_BUTTON, "OwnerGrabButton" },
{ 0, NULL } };
static void
-Display_Event_Mask(long mask)
+Display_Event_Mask (long mask)
{
- long bit, bit_mask;
+ long bit, bit_mask;
- for (bit=0, bit_mask=1; bit<sizeof(long)*8; bit++, bit_mask <<= 1)
- if (mask & bit_mask)
- printf(" %s\n",
- LookupL(bit_mask, _event_mask_names));
+ for (bit=0, bit_mask=1; bit < sizeof(long)*8; bit++, bit_mask <<= 1)
+ if (mask & bit_mask)
+ printf (" %s\n",
+ LookupL (bit_mask, _event_mask_names));
}
/*
* Display info on events
+ *
+ * Requires wininfo members initialized:
+ * window, attr_cookie (or win_attributes)
*/
static void
-Display_Events_Info(Window window)
+Display_Events_Info (struct wininfo *w)
{
- XWindowAttributes win_attributes;
-
- if (!XGetWindowAttributes(dpy, window, &win_attributes))
- Fatal_Error("Can't get window attributes.");
+ xcb_get_window_attributes_reply_t *win_attributes
+ = fetch_win_attributes (w);
- printf("\n");
- printf(" Someone wants these events:\n");
- Display_Event_Mask(win_attributes.all_event_masks);
+ printf ("\n");
+ printf (" Someone wants these events:\n");
+ Display_Event_Mask (win_attributes->all_event_masks);
- printf(" Do not propagate these events:\n");
- Display_Event_Mask(win_attributes.do_not_propagate_mask);
+ printf (" Do not propagate these events:\n");
+ Display_Event_Mask (win_attributes->do_not_propagate_mask);
- printf(" Override redirection?: %s\n",
- Lookup(win_attributes.override_redirect, _bool));
+ printf (" Override redirection?: %s\n",
+ Lookup (win_attributes->override_redirect, _bool));
}
@@ -877,82 +1259,184 @@ Display_Events_Info(Window window)
/*
* Display root, parent, and (recursively) children information
* recurse - true to show children information
+ *
+ * Requires wininfo members initialized: window, tree_cookie
*/
static void
-Display_Tree_Info(Window window, int recurse)
+Display_Tree_Info (struct wininfo *w, int recurse)
{
- display_tree_info_1(window, recurse, 0);
+ display_tree_info_1 (w, recurse, 0);
}
/*
* level - recursion level
*/
static void
-display_tree_info_1(Window window, int recurse, int level)
+display_tree_info_1 (struct wininfo *w, int recurse, int level)
{
- int i, j;
- int rel_x, rel_y, abs_x, abs_y;
- unsigned int width, height, border, depth;
- Window root_win, parent_win;
- unsigned int num_children;
- Window *child_list;
- XClassHint classhint;
-
- if (!XQueryTree(dpy, window, &root_win, &parent_win, &child_list,
- &num_children))
- Fatal_Error("Can't query window tree.");
-
- if (level == 0) {
- printf("\n");
- printf(" Root window id: ");
- Display_Window_Id(root_win, True);
- printf(" Parent window id: ");
- Display_Window_Id(parent_win, True);
- }
-
- if (level == 0 || num_children > 0) {
- printf(" ");
- for (j=0; j<level; j++) printf(" ");
- printf("%d child%s%s\n", num_children, num_children == 1 ? "" : "ren",
- num_children ? ":" : ".");
- }
-
- for (i = (int)num_children - 1; i >= 0; i--) {
- printf(" ");
- for (j=0; j<level; j++) printf(" ");
- Display_Window_Id(child_list[i], False);
- printf(": (");
- if(XGetClassHint(dpy, child_list[i], &classhint)) {
- if(classhint.res_name) {
- printf("\"%s\" ", classhint.res_name);
- XFree(classhint.res_name);
- } else
- printf("(none) ");
- if(classhint.res_class) {
- printf("\"%s\") ", classhint.res_class);
- XFree(classhint.res_class);
- } else
- printf("(none)) ");
- } else
- printf(") ");
+ int i, j;
+ unsigned int num_children;
+ xcb_query_tree_reply_t *tree;
+
+ tree = xcb_query_tree_reply (dpy, w->tree_cookie, &err);
+ if (!tree) {
+ Print_X_Error (dpy, err);
+ Fatal_Error ("Can't query window tree.");
+ }
+
+ if (level == 0) {
+ struct wininfo rw, pw;
+ rw.window = tree->root;
+ rw.net_wm_name_cookie = get_net_wm_name (dpy, rw.window);
+ rw.wm_name_cookie = xcb_get_wm_name (dpy, rw.window);
+ pw.window = tree->parent;
+ pw.net_wm_name_cookie = get_net_wm_name (dpy, pw.window);
+ pw.wm_name_cookie = xcb_get_wm_name (dpy, pw.window);
+ xcb_flush (dpy);
+
+ printf ("\n");
+ printf (" Root window id: ");
+ Display_Window_Id (&rw, True);
+ printf (" Parent window id: ");
+ Display_Window_Id (&pw, True);
+ }
+
+ num_children = xcb_query_tree_children_length (tree);
- if (XGetGeometry(dpy, child_list[i], &root_win,
- &rel_x, &rel_y, &width, &height, &border, &depth)) {
- Window child;
+ if (level == 0 || num_children > 0) {
+ printf (" ");
+ for (j = 0; j < level; j++) printf (" ");
+ printf ("%d child%s%s\n", num_children, num_children == 1 ? "" : "ren",
+ num_children ? ":" : ".");
+ }
- printf (" %ux%u+%d+%d", width, height, rel_x, rel_y);
- if (XTranslateCoordinates (dpy, child_list[i], root_win,
- 0 ,0, &abs_x, &abs_y, &child)) {
- printf (" +%d+%d", abs_x - border, abs_y - border);
+ if (num_children > 0) {
+ xcb_window_t *child_list = xcb_query_tree_children (tree);
+ struct wininfo *children
+ = calloc (num_children, sizeof(struct wininfo));
+
+ if (children == NULL)
+ Fatal_Error ("Failed to allocate memory in display_tree_info");
+
+ for (i = (int)num_children - 1; i >= 0; i--) {
+ struct wininfo *cw = &children[i];
+
+ cw->window = child_list[i];
+ cw->net_wm_name_cookie = get_net_wm_name (dpy, child_list[i]);
+ cw->wm_name_cookie = xcb_get_wm_name (dpy, child_list[i]);
+ cw->wm_class_cookie = xcb_get_wm_class (dpy, child_list[i]);
+ cw->geometry_cookie = xcb_get_geometry (dpy, child_list[i]);
+ cw->trans_coords_cookie = xcb_translate_coordinates
+ (dpy, child_list[i], tree->root, 0, 0);
+ if (recurse)
+ cw->tree_cookie = xcb_query_tree (dpy, child_list[i]);
}
+ xcb_flush (dpy);
+
+ for (i = (int)num_children - 1; i >= 0; i--) {
+ struct wininfo *cw = &children[i];
+ Bool got_wm_class = False;
+ char *instance_name = NULL, *class_name = NULL;
+ int instance_name_len, class_name_len;
+#ifdef USE_XCB_ICCCM
+ xcb_get_wm_class_reply_t classhint;
+#else
+ xcb_get_property_reply_t *classprop;
+#endif
+ xcb_get_geometry_reply_t *geometry;
+
+ printf (" ");
+ for (j = 0; j < level; j++) printf (" ");
+ Display_Window_Id (cw, False);
+ printf (": (");
+
+#ifdef USE_XCB_ICCCM
+ if (xcb_get_wm_class_reply (dpy, cw->wm_class_cookie,
+ &classhint, NULL)) {
+ got_wm_class = True;
+ instance_name = classhint.instance_name;
+ class_name = classhint.class_name;
+ instance_name_len = strlen(instance_name);
+ class_name_len = strlen(class_name);
+ }
+#else
+ classprop = xcb_get_property_reply
+ (dpy, cw->wm_class_cookie, NULL);
+ if (classprop) {
+ if (classprop->type == XCB_ATOM_STRING &&
+ classprop->format == 8) {
+ int proplen = xcb_get_property_value_length (classprop);
+
+ instance_name = xcb_get_property_value (classprop);
+ instance_name_len = strnlen (instance_name, proplen);
+ if (instance_name_len < proplen) {
+ class_name = instance_name + instance_name_len + 1;
+ class_name_len = strnlen
+ (class_name, proplen - (instance_name_len + 1));
+ } else
+ class_name_len = 0;
+ got_wm_class = True;
+ }
+ else
+ free (classprop);
+ }
+#endif
+
+ if (got_wm_class) {
+ if (instance_name)
+ printf ("\"%.*s\" ", instance_name_len, instance_name);
+ else
+ printf ("(none) ");
+
+ if (class_name)
+ printf ("\"%.*s\") ", class_name_len, class_name);
+ else
+ printf ("(none)) ");
+
+#ifdef USE_XCB_ICCCM
+ xcb_get_wm_class_reply_wipe (&classhint);
+#else
+ free (classprop);
+#endif
+ } else
+ printf (") ");
+
+ geometry = xcb_get_geometry_reply(dpy, cw->geometry_cookie, &err);
+ if (geometry) {
+ xcb_translate_coordinates_reply_t *trans_coords;
+
+ printf (" %ux%u+%d+%d", geometry->width, geometry->height,
+ geometry->x, geometry->y);
+
+ trans_coords = xcb_translate_coordinates_reply
+ (dpy, cw->trans_coords_cookie, &err);
+
+ if (trans_coords) {
+ int16_t abs_x = (int16_t) trans_coords->dst_x;
+ int16_t abs_y = (int16_t) trans_coords->dst_y;
+ int border = geometry->border_width;
+
+ printf (" +%d+%d", abs_x - border, abs_y - border);
+ free (trans_coords);
+ } else if (err) {
+ Print_X_Error (dpy, err);
+ }
+
+ free (geometry);
+ } else if (err) {
+ Print_X_Error (dpy, err);
+ }
+ printf ("\n");
+
+ if (recurse)
+ display_tree_info_1 (cw, 1, level+1);
+
+ wininfo_wipe (cw);
+ }
+ free (children);
}
- printf("\n");
-
- if (recurse)
- display_tree_info_1(child_list[i], 1, level+1);
- }
- if (child_list) XFree((char *)child_list);
+ free (tree); /* includes storage for child_list[] */
}
@@ -960,77 +1444,77 @@ display_tree_info_1(Window window, int recurse, int level)
* Display a set of size hints
*/
static void
-Display_Hints(XSizeHints *hints)
+Display_Hints (xcb_size_hints_t *hints)
{
- long flags;
+ long flags;
- flags = hints->flags;
-
- if (flags & USPosition)
- printf(" User supplied location: %s, %s\n",
- xscale(hints->x), yscale(hints->y));
+ flags = hints->flags;
- if (flags & PPosition)
- printf(" Program supplied location: %s, %s\n",
- xscale(hints->x), yscale(hints->y));
+ if (flags & XCB_SIZE_HINT_US_POSITION)
+ printf (" User supplied location: %s, %s\n",
+ xscale (hints->x), yscale (hints->y));
- if (flags & USSize) {
- printf(" User supplied size: %s by %s\n",
- xscale(hints->width), yscale(hints->height));
- }
+ if (flags & XCB_SIZE_HINT_P_POSITION)
+ printf (" Program supplied location: %s, %s\n",
+ xscale (hints->x), yscale (hints->y));
- if (flags & PSize)
- printf(" Program supplied size: %s by %s\n",
- xscale(hints->width), yscale(hints->height));
+ if (flags & XCB_SIZE_HINT_US_SIZE) {
+ printf (" User supplied size: %s by %s\n",
+ xscale (hints->width), yscale (hints->height));
+ }
- if (flags & PMinSize)
- printf(" Program supplied minimum size: %s by %s\n",
- xscale(hints->min_width), yscale(hints->min_height));
+ if (flags & XCB_SIZE_HINT_P_SIZE)
+ printf (" Program supplied size: %s by %s\n",
+ xscale (hints->width), yscale (hints->height));
- if (flags & PMaxSize)
- printf(" Program supplied maximum size: %s by %s\n",
- xscale(hints->max_width), yscale(hints->max_height));
+ if (flags & XCB_SIZE_HINT_P_MIN_SIZE)
+ printf (" Program supplied minimum size: %s by %s\n",
+ xscale (hints->min_width), yscale (hints->min_height));
- if (flags & PBaseSize) {
- printf(" Program supplied base size: %s by %s\n",
- xscale(hints->base_width), yscale(hints->base_height));
- }
+ if (flags & XCB_SIZE_HINT_P_MAX_SIZE)
+ printf (" Program supplied maximum size: %s by %s\n",
+ xscale (hints->max_width), yscale (hints->max_height));
+
+ if (flags & XCB_SIZE_HINT_BASE_SIZE) {
+ printf (" Program supplied base size: %s by %s\n",
+ xscale (hints->base_width), yscale (hints->base_height));
+ }
- if (flags & PResizeInc) {
- printf(" Program supplied x resize increment: %s\n",
- xscale(hints->width_inc));
- printf(" Program supplied y resize increment: %s\n",
- yscale(hints->height_inc));
- if (hints->width_inc != 0 && hints->height_inc != 0) {
- if (flags & USSize)
- printf(" User supplied size in resize increments: %s by %s\n",
- (xscale(hints->width / hints->width_inc)),
- (yscale(hints->height / hints->height_inc)));
- if (flags & PSize)
- printf(" Program supplied size in resize increments: %s by %s\n",
- (xscale(hints->width / hints->width_inc)),
- (yscale(hints->height / hints->height_inc)));
- if (flags & PMinSize)
- printf(" Program supplied minimum size in resize increments: %s by %s\n",
- xscale(hints->min_width / hints->width_inc), yscale(hints->min_height / hints->height_inc));
- if (flags & PBaseSize)
- printf(" Program supplied base size in resize increments: %s by %s\n",
- (xscale(hints->base_width / hints->width_inc)),
- (yscale(hints->base_height / hints->height_inc)));
- }
- }
-
- if (flags & PAspect) {
- printf(" Program supplied min aspect ratio: %s/%s\n",
- xscale(hints->min_aspect.x), yscale(hints->min_aspect.y));
- printf(" Program supplied max aspect ratio: %s/%s\n",
- xscale(hints->max_aspect.x), yscale(hints->max_aspect.y));
- }
-
- if (flags & PWinGravity) {
- printf(" Program supplied window gravity: %s\n",
- Lookup(hints->win_gravity, _gravities));
+ if (flags & XCB_SIZE_HINT_P_RESIZE_INC) {
+ printf (" Program supplied x resize increment: %s\n",
+ xscale (hints->width_inc));
+ printf (" Program supplied y resize increment: %s\n",
+ yscale (hints->height_inc));
+ if (hints->width_inc != 0 && hints->height_inc != 0) {
+ if (flags & XCB_SIZE_HINT_US_SIZE)
+ printf (" User supplied size in resize increments: %s by %s\n",
+ (xscale (hints->width / hints->width_inc)),
+ (yscale (hints->height / hints->height_inc)));
+ if (flags & XCB_SIZE_HINT_P_SIZE)
+ printf (" Program supplied size in resize increments: %s by %s\n",
+ (xscale (hints->width / hints->width_inc)),
+ (yscale (hints->height / hints->height_inc)));
+ if (flags & XCB_SIZE_HINT_P_MIN_SIZE)
+ printf (" Program supplied minimum size in resize increments: %s by %s\n",
+ xscale (hints->min_width / hints->width_inc), yscale (hints->min_height / hints->height_inc));
+ if (flags & XCB_SIZE_HINT_BASE_SIZE)
+ printf (" Program supplied base size in resize increments: %s by %s\n",
+ (xscale (hints->base_width / hints->width_inc)),
+ (yscale (hints->base_height / hints->height_inc)));
}
+ }
+
+ if (flags & XCB_SIZE_HINT_P_ASPECT) {
+ printf (" Program supplied min aspect ratio: %s/%s\n",
+ xscale (hints->min_aspect_num), yscale (hints->min_aspect_den));
+ printf (" Program supplied max aspect ratio: %s/%s\n",
+ xscale (hints->max_aspect_num), yscale (hints->max_aspect_den));
+ }
+
+ if (flags & XCB_SIZE_HINT_P_WIN_GRAVITY) {
+ printf (" Program supplied window gravity: %s\n",
+ Lookup (hints->win_gravity, _gravities));
+ }
}
@@ -1038,103 +1522,463 @@ Display_Hints(XSizeHints *hints)
* Display Size Hints info
*/
static void
-Display_Size_Hints(Window window)
+Display_Size_Hints (struct wininfo *w)
{
- XSizeHints *hints = XAllocSizeHints();
- long supplied;
-
- printf("\n");
- if (!XGetWMNormalHints(dpy, window, hints, &supplied))
- printf(" No normal window size hints defined\n");
- else {
- printf(" Normal window size hints:\n");
- hints->flags &= supplied;
- Display_Hints(hints);
- }
+ xcb_size_hints_t hints;
- if (!XGetWMSizeHints(dpy, window, hints, &supplied, XA_WM_ZOOM_HINTS))
- printf(" No zoom window size hints defined\n");
- else {
- printf(" Zoom window size hints:\n");
- hints->flags &= supplied;
- Display_Hints(hints);
- }
- XFree((char *)hints);
+ printf ("\n");
+ if (!fetch_normal_hints (w, &hints))
+ printf (" No normal window size hints defined\n");
+ else {
+ printf (" Normal window size hints:\n");
+ Display_Hints (&hints);
+ }
+
+ if (!xcb_get_wm_size_hints_reply (dpy, w->zoom_cookie, &hints, NULL))
+ printf (" No zoom window size hints defined\n");
+ else {
+ printf (" Zoom window size hints:\n");
+ Display_Hints (&hints);
+ }
}
static void
-Display_Window_Shape (Window window)
+Display_Window_Shape (xcb_window_t window)
{
- Bool ws, bs;
- int xws, yws, xbs, ybs;
- unsigned int wws, hws, wbs, hbs;
+ const xcb_query_extension_reply_t *shape_query;
+ xcb_shape_query_extents_cookie_t extents_cookie;
+ xcb_shape_query_extents_reply_t *extents;
+
+ shape_query = xcb_get_extension_data (dpy, &xcb_shape_id);
+ if (!shape_query->present)
+ return;
+
+ printf ("\n");
- if (!XShapeQueryExtension (dpy, &bs, &ws))
+ extents_cookie = xcb_shape_query_extents (dpy, window);
+ extents = xcb_shape_query_extents_reply (dpy, extents_cookie, &err);
+
+ if (!extents) {
+ if (err)
+ Print_X_Error (dpy, err);
+ else
+ {
+ printf (" No window shape defined\n");
+ printf (" No border shape defined\n");
+ }
return;
+ }
- printf("\n");
- XShapeQueryExtents (dpy, window, &ws, &xws, &yws, &wws, &hws,
- &bs, &xbs, &ybs, &wbs, &hbs);
- if (!ws)
- printf(" No window shape defined\n");
+ if (!extents->bounding_shaped)
+ printf (" No window shape defined\n");
else {
- printf(" Window shape extents: %sx%s",
- xscale(wws), yscale(hws));
- printf("+%s+%s\n", xscale(xws), yscale(yws));
+ printf (" Window shape extents: %sx%s",
+ xscale (extents->bounding_shape_extents_width),
+ yscale (extents->bounding_shape_extents_height));
+ printf ("+%s+%s\n",
+ xscale (extents->bounding_shape_extents_x),
+ yscale (extents->bounding_shape_extents_y));
}
- if (!bs)
- printf(" No border shape defined\n");
+ if (!extents->clip_shaped)
+ printf (" No border shape defined\n");
else {
- printf(" Border shape extents: %sx%s",
- xscale(wbs), yscale(hbs));
- printf("+%s+%s\n", xscale(xbs), yscale(ybs));
+ printf (" Border shape extents: %sx%s",
+ xscale (extents->clip_shape_extents_width),
+ yscale (extents->clip_shape_extents_height));
+ printf ("+%s+%s\n",
+ xscale (extents->clip_shape_extents_x),
+ yscale (extents->clip_shape_extents_y));
}
+
+ free (extents);
}
/*
* Display Window Manager Info
+ *
+ * Requires wininfo members initialized:
+ * window, hints_cookie
*/
static const binding _state_hints[] = {
- { DontCareState, "Don't Care State" },
- { NormalState, "Normal State" },
- { ZoomState, "Zoomed State" },
- { IconicState, "Iconic State" },
- { InactiveState, "Inactive State" },
+ { XCB_WM_STATE_WITHDRAWN, "Withdrawn State" },
+ { XCB_WM_STATE_NORMAL, "Normal State" },
+ { XCB_WM_STATE_ICONIC, "Iconic State" },
+/* xwininfo previously also reported the ZoomState & InactiveState,
+ but ICCCM declared those obsolete long ago */
{ 0, NULL } };
+#ifndef USE_XCB_ICCCM
+static Bool
+wm_hints_reply (xcb_connection_t *dpy, xcb_get_property_cookie_t cookie,
+ wm_hints_t *hints_return, xcb_generic_error_t **err)
+{
+ xcb_get_property_reply_t *prop = xcb_get_property_reply (dpy, cookie, err);
+ int length;
+
+ if (!prop || (prop->type != XCB_ATOM_WM_HINTS) || (prop->format != 32)) {
+ free (prop);
+ return False;
+ }
+
+ memset (hints_return, 0, sizeof(wm_hints_t));
+
+ length = xcb_get_property_value_length(prop);
+ if (length > sizeof(wm_hints_t))
+ length = sizeof(wm_hints_t);
+ memcpy (hints_return, xcb_get_property_value (prop), length);
+
+ free (prop);
+ return True;
+}
+
+#define xcb_get_wm_hints_reply wm_hints_reply
+#endif
+
static void
-Display_WM_Info(Window window)
+Display_WM_Info (struct wininfo *w)
{
- XWMHints *wmhints;
- long flags;
-
- wmhints = XGetWMHints(dpy, window);
- printf("\n");
- if (!wmhints) {
- printf(" No window manager hints defined\n");
- return;
+ xcb_wm_hints_t wmhints;
+ long flags;
+ xcb_get_property_reply_t *prop;
+ int i;
+
+ printf ("\n");
+ if (!xcb_get_wm_hints_reply(dpy, w->hints_cookie, &wmhints, &err))
+ {
+ printf (" No window manager hints defined\n");
+ if (err)
+ Print_X_Error (dpy, err);
+ flags = 0;
+ } else
+ flags = wmhints.flags;
+
+ printf (" Window manager hints:\n");
+
+ if (flags & XCB_WM_HINT_INPUT)
+ printf (" Client accepts input or input focus: %s\n",
+ Lookup (wmhints.input, _bool));
+
+ if (flags & XCB_WM_HINT_ICON_WINDOW) {
+ struct wininfo iw;
+ iw.window = wmhints.icon_window;
+ iw.net_wm_name_cookie = get_net_wm_name (dpy, iw.window);
+ iw.wm_name_cookie = xcb_get_wm_name (dpy, iw.window);
+
+ printf (" Icon window id: ");
+ Display_Window_Id (&iw, True);
+ }
+
+ if (flags & XCB_WM_HINT_ICON_POSITION)
+ printf (" Initial icon position: %s, %s\n",
+ xscale (wmhints.icon_x), yscale (wmhints.icon_y));
+
+ if (flags & XCB_WM_HINT_STATE)
+ printf (" Initial state is %s\n",
+ Lookup (wmhints.initial_state, _state_hints));
+
+ if (atom_net_wm_desktop) {
+ prop = xcb_get_property_reply (dpy, w->wm_desktop_cookie, NULL);
+ if (prop && (prop->type != XCB_NONE)) {
+ uint32_t *desktop = xcb_get_property_value (prop);
+ if (*desktop == 0xFFFFFFFF) {
+ printf (" Displayed on all desktops\n");
+ } else {
+ printf (" Displayed on desktop %d\n", *desktop);
+ }
}
- flags = wmhints->flags;
+ free (prop);
+ }
+
+ if (atom_net_wm_window_type) {
+ prop = xcb_get_property_reply (dpy, w->wm_window_type_cookie,
+ NULL);
+ if (prop && (prop->type != XCB_NONE) && (prop->value_len > 0)) {
+ xcb_atom_t *atoms = xcb_get_property_value (prop);
+ int atom_count = prop->value_len;
+
+ if (atom_count > 0) {
+ printf (" Window type:\n");
+ for (i = 0; i < atom_count; i++) {
+ const char *atom_name = Get_Atom_Name (dpy, atoms[i]);
+
+ if (atom_name) {
+ print_friendly_name (" %s\n", atom_name,
+ "_NET_WM_WINDOW_TYPE_");
+ } else {
+ printf (" (unresolvable ATOM 0x%x)\n",
+ atoms[i]);
+ }
+ }
+ }
+ }
+ free (prop);
+ }
+
+ if (atom_net_wm_state) {
+ prop = xcb_get_property_reply (dpy, w->wm_state_cookie, NULL);
+ if (prop && (prop->type != XCB_NONE) && (prop->value_len > 0)) {
+ xcb_atom_t *atoms = xcb_get_property_value (prop);
+ int atom_count = prop->value_len;
+
+ if (atom_count > 0) {
+ printf (" Window state:\n");
+ for (i = 0; i < atom_count; i++) {
+ const char *atom_name = Get_Atom_Name (dpy, atoms[i]);
+
+ if (atom_name) {
+ print_friendly_name (" %s\n", atom_name,
+ "_NET_WM_STATE_");
+ } else {
+ printf (" (unresolvable ATOM 0x%x)\n",
+ atoms[i]);
+ }
+ }
+ }
+ }
+ free (prop);
+ }
+
+ if (atom_net_wm_pid) {
+ printf (" Process id: ");
+ prop = xcb_get_property_reply (dpy, w->wm_pid_cookie, NULL);
+ if (prop && (prop->type == XCB_ATOM_CARDINAL)) {
+ uint32_t *pid = xcb_get_property_value (prop);
+ printf ("%d", *pid);
+ } else {
+ printf ("(unknown)");
+ }
+ free (prop);
- printf(" Window manager hints:\n");
+ prop = xcb_get_property_reply (dpy, w->wm_client_machine_cookie, NULL);
+ if (prop && (prop->type == XCB_ATOM_STRING)) {
+ const char *hostname = xcb_get_property_value (prop);
+ int hostname_len = xcb_get_property_value_length (prop);
+ printf (" on host %.*s", hostname_len, hostname);
+ }
+ printf ("\n");
+ free (prop);
+ }
- if (flags & InputHint)
- printf(" Client accepts input or input focus: %s\n",
- Lookup(wmhints->input, _bool));
+ if (atom_net_frame_extents) {
+ prop = xcb_get_property_reply (dpy, w->frame_extents_cookie, NULL);
+ if (prop && (prop->type == XCB_ATOM_CARDINAL)
+ && (prop->value_len == 4)) {
+ uint32_t *extents = xcb_get_property_value (prop);
- if (flags & IconWindowHint) {
- printf(" Icon window id: ");
- Display_Window_Id(wmhints->icon_window, True);
+ printf (" Frame extents: %d, %d, %d, %d\n",
+ extents[0], extents[1], extents[2], extents[3]);
}
+ free (prop);
+ }
+}
- if (flags & IconPositionHint)
- printf(" Initial icon position: %s, %s\n",
- xscale(wmhints->icon_x), yscale(wmhints->icon_y));
+/* Frees all members of a wininfo struct, but not the struct itself */
+static void
+wininfo_wipe (struct wininfo *w)
+{
+ free (w->geometry);
+ free (w->win_attributes);
+ free (w->normal_hints);
+}
- if (flags & StateHint)
- printf(" Initial state is %s\n",
- Lookup(wmhints->initial_state, _state_hints));
+/* Gets UTF-8 encoded EMWH property _NET_WM_NAME for a window */
+static xcb_get_property_cookie_t
+get_net_wm_name (xcb_connection_t *dpy, xcb_window_t win)
+{
+ if (!atom_net_wm_name)
+ atom_net_wm_name = Get_Atom (dpy, "_NET_WM_NAME");
+
+ if (!atom_utf8_string)
+ atom_utf8_string = Get_Atom (dpy, "UTF8_STRING");
+
+ if (atom_net_wm_name && atom_utf8_string)
+ return xcb_get_property (dpy, False, win, atom_net_wm_name,
+ atom_utf8_string, 0, BUFSIZ);
+ else {
+ xcb_get_property_cookie_t dummy = { 0 };
+ return dummy;
+ }
+}
+
+/* [Copied from code added by Yang Zhao to xprop/xprop.c]
+ *
+ * Validate a string as UTF-8 encoded according to RFC 3629
+ *
+ * Simply, a unicode code point (up to 21-bits long) is encoded as follows:
+ *
+ * Char. number range | UTF-8 octet sequence
+ * (hexadecimal) | (binary)
+ * --------------------+---------------------------------------------
+ * 0000 0000-0000 007F | 0xxxxxxx
+ * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+ * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+ * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *
+ * Validation is done left-to-right, and an error condition, if any, refers to
+ * only the left-most problem in the string.
+ *
+ * Return values:
+ * UTF8_VALID: Valid UTF-8 encoded string
+ * UTF8_OVERLONG: Using more bytes than needed for a code point
+ * UTF8_SHORT_TAIL: Not enough bytes in a multi-byte sequence
+ * UTF8_LONG_TAIL: Too many bytes in a multi-byte sequence
+ * UTF8_FORBIDDEN_VALUE: Forbidden prefix or code point outside 0x10FFFF
+ */
+#define UTF8_VALID 0
+#define UTF8_FORBIDDEN_VALUE 1
+#define UTF8_OVERLONG 2
+#define UTF8_SHORT_TAIL 3
+#define UTF8_LONG_TAIL 4
+static int
+is_valid_utf8 (const char *string, int len)
+{
+ unsigned long codepoint;
+ int rem, i;
+ unsigned char c;
+
+ rem = 0;
+ for (i = 0; i < len; i++) {
+ c = (unsigned char) string[i];
+
+ /* Order of type check:
+ * - Single byte code point
+ * - Non-starting byte of multi-byte sequence
+ * - Start of 2-byte sequence
+ * - Start of 3-byte sequence
+ * - Start of 4-byte sequence
+ */
+ if (!(c & 0x80)) {
+ if (rem > 0) return UTF8_SHORT_TAIL;
+ rem = 0;
+ codepoint = c;
+ } else if ((c & 0xC0) == 0x80) {
+ if (rem == 0) return UTF8_LONG_TAIL;
+ rem--;
+ codepoint |= (c & 0x3F) << (rem * 6);
+ if (codepoint == 0) return UTF8_OVERLONG;
+ } else if ((c & 0xE0) == 0xC0) {
+ if (rem > 0) return UTF8_SHORT_TAIL;
+ rem = 1;
+ codepoint = (c & 0x1F) << 6;
+ if (codepoint == 0) return UTF8_OVERLONG;
+ } else if ((c & 0xF0) == 0xE0) {
+ if (rem > 0) return UTF8_SHORT_TAIL;
+ rem = 2;
+ codepoint = (c & 0x0F) << 12;
+ } else if ((c & 0xF8) == 0xF0) {
+ if (rem > 0) return UTF8_SHORT_TAIL;
+ rem = 3;
+ codepoint = (c & 0x07) << 18;
+ if (codepoint > 0x10FFFF) return UTF8_FORBIDDEN_VALUE;
+ } else
+ return UTF8_FORBIDDEN_VALUE;
+ }
+
+ return UTF8_VALID;
+}
+
+/*
+ * Converts a UTF-8 encoded string to the current locale encoding,
+ * if possible, and prints it, with prefix before and suffix after.
+ * Length of the string is specified in bytes, or -1 for going until '\0'
+ */
+static void
+print_utf8 (const char *prefix, char *u8str, size_t length, const char *suffix)
+{
+ size_t inlen = length;
+
+ if (inlen < 0) {
+ inlen = strlen (u8str);
+ }
+
+ if (is_valid_utf8 (u8str, inlen) != UTF8_VALID) {
+ printf (" (invalid UTF8_STRING)");
+ return;
+ }
+
+ if (strcmp (user_encoding, "UTF-8") == 0) {
+ /* Don't need to convert */
+ printf ("%s", prefix);
+ fwrite (u8str, 1, inlen, stdout);
+ printf ("%s", suffix);
+ return;
+ }
+
+#ifdef HAVE_ICONV
+ if (!iconv_from_utf8) {
+ iconv_from_utf8 = iconv_open (user_encoding, "UTF-8");
+ }
+
+ if (iconv_from_utf8 != (iconv_t) -1) {
+ Bool done = True;
+ char *inp = u8str;
+ char convbuf[BUFSIZ];
+ int convres;
+
+ printf ("%s", prefix);
+ do {
+ char *outp = convbuf;
+ size_t outlen = sizeof(convbuf);
+
+ convres = iconv (iconv_from_utf8, &inp, &inlen, &outp, &outlen);
+
+ if ((convres == -1) && (errno == E2BIG)) {
+ done = False;
+ convres = 0;
+ }
+
+ if (convres == 0) {
+ fwrite (convbuf, 1, sizeof(convbuf) - outlen, stdout);
+ } else {
+ printf (" (failure in conversion from UTF8_STRING to %s)",
+ user_encoding);
+ }
+ } while (!done);
+ printf ("%s", suffix);
+ } else {
+ printf (" (can't load iconv conversion for UTF8_STRING to %s)",
+ user_encoding);
+ }
+#else
+ printf (" (can't convert UTF8_STRING to %s)", user_encoding);
+#endif
+}
+
+/*
+ * Takes a string such as an atom name, strips the prefix, converts
+ * underscores to spaces, lowercases all but the first letter of each word,
+ * and prints it.
+ */
+static void
+print_friendly_name (const char *format, const char *string,
+ const char *prefix)
+{
+ const char *name_start = string;
+ char *lowered_name, *n;
+ int prefix_len = strlen (prefix);
+
+ if (strncmp (name_start, prefix, prefix_len) == 0) {
+ name_start += prefix_len;
+ }
+
+ lowered_name = strdup (name_start);
+ if (lowered_name) {
+ Bool first = True;
+
+ for (n = lowered_name ; *n != 0 ; n++) {
+ if (*n == '_') {
+ *n = ' ';
+ first = True;
+ } else if (first) {
+ first = False;
+ } else {
+ *n = tolower(*n);
+ }
+ }
+ name_start = lowered_name;
+ }
- XFree(wmhints);
+ printf (format, name_start);
+ free (lowered_name);
}