From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- apps/xwininfo/Makefile.am | 92 +- apps/xwininfo/configure.ac | 152 +- apps/xwininfo/xwininfo.c | 3966 ++++++++++++++++++++++---------------------- 3 files changed, 2105 insertions(+), 2105 deletions(-) (limited to 'apps/xwininfo') diff --git a/apps/xwininfo/Makefile.am b/apps/xwininfo/Makefile.am index 2204b3486..1bb066468 100644 --- a/apps/xwininfo/Makefile.am +++ b/apps/xwininfo/Makefile.am @@ -1,46 +1,46 @@ -# -# Copyright 2005 Red Hat, Inc. -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of Red Hat not be used in -# advertising or publicity pertaining to distribution of the software without -# specific, written prior permission. Red Hat makes no -# representations about the suitability of this software for any purpose. It -# is provided "as is" without express or implied warranty. -# -# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -SUBDIRS = man -bin_PROGRAMS = xwininfo - -AM_CFLAGS = $(CWARNFLAGS) $(XWININFO_CFLAGS) -xwininfo_LDADD = $(XWININFO_LIBS) $(LIBOBJS) - -xwininfo_SOURCES = \ - clientwin.c \ - clientwin.h \ - dsimple.c \ - dsimple.h \ - xwininfo.c - -EXTRA_DIST = strnlen.h -MAINTAINERCLEANFILES = ChangeLog INSTALL - -.PHONY: ChangeLog INSTALL - -INSTALL: - $(INSTALL_CMD) - -ChangeLog: - $(CHANGELOG_CMD) - -dist-hook: ChangeLog INSTALL +# +# Copyright 2005 Red Hat, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +SUBDIRS = man +bin_PROGRAMS = xwininfo + +AM_CFLAGS = $(CWARNFLAGS) $(XWININFO_CFLAGS) +xwininfo_LDADD = $(XWININFO_LIBS) $(LIBOBJS) + +xwininfo_SOURCES = \ + clientwin.c \ + clientwin.h \ + dsimple.c \ + dsimple.h \ + xwininfo.c + +EXTRA_DIST = strnlen.h +MAINTAINERCLEANFILES = ChangeLog INSTALL + +.PHONY: ChangeLog INSTALL + +INSTALL: + $(INSTALL_CMD) + +ChangeLog: + $(CHANGELOG_CMD) + +dist-hook: ChangeLog INSTALL diff --git a/apps/xwininfo/configure.ac b/apps/xwininfo/configure.ac index 53bccfecc..e712ba661 100644 --- a/apps/xwininfo/configure.ac +++ b/apps/xwininfo/configure.ac @@ -1,76 +1,76 @@ - -dnl Copyright 2005 Red Hat, Inc. -dnl -dnl Permission to use, copy, modify, distribute, and sell this software and its -dnl documentation for any purpose is hereby granted without fee, provided that -dnl the above copyright notice appear in all copies and that both that -dnl copyright notice and this permission notice appear in supporting -dnl documentation, and that the name of Red Hat not be used in -dnl advertising or publicity pertaining to distribution of the software without -dnl specific, written prior permission. Red Hat makes no -dnl representations about the suitability of this software for any purpose. It -dnl is provided "as is" without express or implied warranty. -dnl -dnl RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -dnl INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -dnl EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR -dnl CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -dnl DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -dnl TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -dnl PERFORMANCE OF THIS SOFTWARE. -dnl -dnl Process this file with autoconf to create configure. - -AC_PREREQ([2.60]) -AC_INIT([xwininfo], [1.1.2], - [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xwininfo]) -AM_INIT_AUTOMAKE([foreign dist-bzip2]) -AM_MAINTAINER_MODE - -# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS -m4_ifndef([XORG_MACROS_VERSION], - [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) -XORG_MACROS_VERSION(1.8) - -AC_CONFIG_HEADERS([config.h]) - -AC_USE_SYSTEM_EXTENSIONS - -XORG_DEFAULT_OPTIONS - -AC_CHECK_FUNCS([strlcat]) - -AC_FUNC_STRNLEN -if test "x$ac_cv_func_strnlen_working" = xyes; then - AC_DEFINE(HAVE_STRNLEN, 1, [Define to 1 if you have a working strnlen function.]) -fi - -AM_ICONV - -# Allow using xcb-icccm, but don't make it the default while the API is -# still being changed. -AC_MSG_CHECKING([whether to use xcb-icccm library]) -AC_ARG_WITH([xcb-icccm], - [AS_HELP_STRING([--with-xcb-icccm], - [use xcb-icccm (default: no)])], - [], [with_xcb_icccm=no]) -AC_MSG_RESULT([$with_xcb_icccm]) -if test "x$with_xcb_icccm" != xno ; then - AC_DEFINE([USE_XCB_ICCCM], 1, - [Define to 1 to call xcb-icccm library functions instead of local replacements]) - xcb_icccm_pc='xcb-icccm >= 0.3.8' -fi - -# Checks for pkg-config packages -PKG_CHECK_MODULES(XWININFO, [xcb >= 1.6] xcb-shape ${xcb_icccm_pc}) - -# Even when using xcb, xproto is still required for Xfuncproto.h -# and libX11 headers for cursorfont.h -PKG_CHECK_MODULES(XLIB, x11 [xproto >= 7.0.17]) -XWININFO_CFLAGS="${XWININFO_CFLAGS} ${XLIB_CFLAGS}" -XWININFO_LIBS="${XWININFO_LIBS} ${LIBICONV}" - -AC_CONFIG_FILES([ - Makefile - man/Makefile]) -AC_OUTPUT + +dnl Copyright 2005 Red Hat, Inc. +dnl +dnl Permission to use, copy, modify, distribute, and sell this software and its +dnl documentation for any purpose is hereby granted without fee, provided that +dnl the above copyright notice appear in all copies and that both that +dnl copyright notice and this permission notice appear in supporting +dnl documentation, and that the name of Red Hat not be used in +dnl advertising or publicity pertaining to distribution of the software without +dnl specific, written prior permission. Red Hat makes no +dnl representations about the suitability of this software for any purpose. It +dnl is provided "as is" without express or implied warranty. +dnl +dnl RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +dnl INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +dnl EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +dnl CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +dnl DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +dnl TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +dnl PERFORMANCE OF THIS SOFTWARE. +dnl +dnl Process this file with autoconf to create configure. + +AC_PREREQ([2.60]) +AC_INIT([xwininfo], [1.1.2], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xwininfo]) +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_MAINTAINER_MODE + +# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.8) + +AC_CONFIG_HEADERS([config.h]) + +AC_USE_SYSTEM_EXTENSIONS + +XORG_DEFAULT_OPTIONS + +AC_CHECK_FUNCS([strlcat]) + +AC_FUNC_STRNLEN +if test "x$ac_cv_func_strnlen_working" = xyes; then + AC_DEFINE(HAVE_STRNLEN, 1, [Define to 1 if you have a working strnlen function.]) +fi + +AM_ICONV + +# Allow using xcb-icccm, but don't make it the default while the API is +# still being changed. +AC_MSG_CHECKING([whether to use xcb-icccm library]) +AC_ARG_WITH([xcb-icccm], + [AS_HELP_STRING([--with-xcb-icccm], + [use xcb-icccm (default: no)])], + [], [with_xcb_icccm=no]) +AC_MSG_RESULT([$with_xcb_icccm]) +if test "x$with_xcb_icccm" != xno ; then + AC_DEFINE([USE_XCB_ICCCM], 1, + [Define to 1 to call xcb-icccm library functions instead of local replacements]) + xcb_icccm_pc='xcb-icccm >= 0.3.8' +fi + +# Checks for pkg-config packages +PKG_CHECK_MODULES(XWININFO, [xcb >= 1.6] xcb-shape ${xcb_icccm_pc}) + +# Even when using xcb, xproto is still required for Xfuncproto.h +# and libX11 headers for cursorfont.h +PKG_CHECK_MODULES(XLIB, x11 [xproto >= 7.0.17]) +XWININFO_CFLAGS="${XWININFO_CFLAGS} ${XLIB_CFLAGS}" +XWININFO_LIBS="${XWININFO_LIBS} ${LIBICONV}" + +AC_CONFIG_FILES([ + Makefile + man/Makefile]) +AC_OUTPUT diff --git a/apps/xwininfo/xwininfo.c b/apps/xwininfo/xwininfo.c index b1dfb0dc7..af1354d46 100644 --- a/apps/xwininfo/xwininfo.c +++ b/apps/xwininfo/xwininfo.c @@ -1,1983 +1,1983 @@ -/* - * 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 - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -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 -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. - -*/ - - -/* - * xwininfo.c - MIT Project Athena, X Window system window - * information utility. - * - * - * This program will report all relevant information - * about a specific window. - * - * Author: Mark Lillibridge, MIT Project Athena - * 16-Jun-87 - */ - -#include "config.h" - -#include -#include -#ifdef USE_XCB_ICCCM -# include -#endif -#include - -#include -#include -#include -#include -#include -#ifndef _MSC_VER -#include -#endif -#ifdef HAVE_ICONV -# include -#endif -#include -#include - -#ifndef HAVE_STRNLEN -#include "strnlen.h" -#endif - -/* Include routines to handle parsing defaults */ -#include "dsimple.h" - -typedef struct { - long code; - const char *name; -} binding; - -#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_icccm_wm_hints_t wm_hints_t - -enum { - /* xcb_size_hints_flags_t */ - XCB_ICCCM_SIZE_HINT_US_POSITION = 1 << 0, - XCB_ICCCM_SIZE_HINT_US_SIZE = 1 << 1, - XCB_ICCCM_SIZE_HINT_P_POSITION = 1 << 2, - XCB_ICCCM_SIZE_HINT_P_SIZE = 1 << 3, - XCB_ICCCM_SIZE_HINT_P_MIN_SIZE = 1 << 4, - XCB_ICCCM_SIZE_HINT_P_MAX_SIZE = 1 << 5, - XCB_ICCCM_SIZE_HINT_P_RESIZE_INC = 1 << 6, - XCB_ICCCM_SIZE_HINT_P_ASPECT = 1 << 7, - XCB_ICCCM_SIZE_HINT_BASE_SIZE = 1 << 8, - XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY = 1 << 9, - /* xcb_wm_state_t */ - XCB_ICCCM_WM_STATE_WITHDRAWN = 0, - XCB_ICCCM_WM_STATE_NORMAL = 1, - XCB_ICCCM_WM_STATE_ICONIC = 3, - /* xcb_wm_t */ - XCB_ICCCM_WM_HINT_INPUT = (1L << 0), - XCB_ICCCM_WM_HINT_STATE = (1L << 1), - XCB_ICCCM_WM_HINT_ICON_PIXMAP = (1L << 2), - XCB_ICCCM_WM_HINT_ICON_WINDOW = (1L << 3), - XCB_ICCCM_WM_HINT_ICON_POSITION = (1L << 4), - XCB_ICCCM_WM_HINT_ICON_MASK = (1L << 5), - XCB_ICCCM_WM_HINT_WINDOW_GROUP = (1L << 6), - XCB_ICCCM_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_icccm_get_wm_name(Dpy, Win) \ - GET_TEXT_PROPERTY(Dpy, Win, XCB_ATOM_WM_NAME) - -# define xcb_icccm_get_wm_class(Dpy, Win) \ - xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, BUFSIZ) -# define xcb_icccm_get_wm_hints(Dpy, Win) \ - xcb_get_property(Dpy, False, Win, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9) - -# define xcb_icccm_get_wm_size_hints(Dpy, Win, Atom) \ - xcb_get_property (Dpy, False, Win, Atom, XCB_ATOM_WM_SIZE_HINTS, 0, 18) -# define xcb_icccm_get_wm_normal_hints(Dpy, Win) \ - xcb_icccm_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) -{ - size_t sd = strlen (dst); - size_t ss = strlen (src); - size_t s = sd + ss; - - if (s < dstsize) { - strcpy (dst + sd, src); - } else { - strncpy (dst + sd, src, dstsize-sd-1); - dst[dstsize] = '\0'; - } - return s; -} -#endif - -/* - * Report the syntax for calling xwininfo: - */ -static void -usage (void) -{ - fprintf (stderr, - "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); -} - -/* - * pixel to inch, metric converter. - * Hacked in by Mark W. Eichin [eichin:19880619.1509EST] - * - * Simply put: replace the old numbers with string print calls. - * Returning a local string is ok, since we only ever get called to - * print one x and one y, so as long as they don't collide, they're - * fine. This is not meant to be a general purpose routine. - * - */ - -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 (xcb_screen_t *screen) -{ - 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) -#define YARD (3*12) -#define FOOT (12) - -static char * -nscale (int n, int np, int nmm, char *nbuf, size_t nbufsize) -{ - int s; - snprintf (nbuf, nbufsize, "%d", n); - - if (metric||english) { - s = strlcat (nbuf, " (", nbufsize); - - if (metric) { - snprintf (nbuf+s, nbufsize-s, "%.2f mm%s", - ((double) n) * nmm/np , english ? "; " : ""); - } - if (english) { - double inch_frac; - Bool printed_anything = False; - int mi, yar, ft, inr; - - inch_frac = ((double) n)*(nmm/25.4)/np; - inr = (int)inch_frac; - inch_frac -= (double)inr; - if (inr >= MILE) { - mi = inr/MILE; - inr %= MILE; - 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"); - 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"); - 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); - } - return (nbuf); -} - -static char xbuf[BUFSIZ]; -static char * -xscale (int x) -{ - return (nscale (x, xp, xmm, xbuf, sizeof(xbuf))); -} - -static char ybuf[BUFSIZ]; -static char * -yscale (int y) -{ - return (nscale (y, yp, ymm, ybuf, sizeof(ybuf))); -} - -static char bbuf[BUFSIZ]; -static char * -bscale (int b) -{ - return (nscale (b, bp, bmm, bbuf, sizeof(bbuf))); -} - -/* end of pixel to inch, metric converter */ - -int -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; - 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 - 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 (); - } - - 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"); - } - /* 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 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); - } - - /* - * 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); - } - } - - /* 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_icccm_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 (stats || bits || events) - w->attr_cookie = xcb_get_window_attributes (dpy, window); - if (stats || size) - w->normal_hints_cookie = xcb_icccm_get_wm_normal_hints (dpy, window); - if (wm) { - w->hints_cookie = xcb_icccm_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 = xcb_get_property - (dpy, False, window, XCB_ATOM_WM_CLIENT_MACHINE, - XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ); - } - - 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 (size) - w->zoom_cookie = xcb_icccm_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); - } -#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."); - } - } - 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; - } - - 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_icccm_get_wm_normal_hints_reply wm_size_hints_reply -#define xcb_icccm_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_icccm_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)); - } - } - if (hints_return && w->normal_hints) - memcpy(hints_return, w->normal_hints, sizeof(xcb_size_hints_t)); - return w->normal_hints; -} - - -/* - * Lookup: lookup a code in a table. - */ -static char _lookup_buffer[100]; - -static const char * -LookupL (long code, const binding *table) -{ - const char *name = NULL; - - 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); -} - -static const char * -Lookup (int code, const binding *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 (struct wininfo *w, Bool newline_wanted) -{ -#ifdef USE_XCB_ICCCM - xcb_icccm_get_text_property_reply_t wmn_reply; - uint8_t got_reply = False; -#endif - xcb_get_property_reply_t *prop; - const char *wm_name = NULL; - unsigned int wm_name_len = 0; - xcb_atom_t wm_name_encoding = XCB_NONE; - - printf (window_id_format, w->window); /* print id # in hex/dec */ - - if (!w->window) { - printf (" (none)"); - } else { - if (w->window == screen->root) { - printf (" (the root window)"); - } - /* 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; - } else { /* No _NET_WM_NAME, check WM_NAME */ -#ifdef USE_XCB_ICCCM - got_reply = xcb_icccm_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 - 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; - } -#endif - } - if (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_icccm_get_text_property_reply_wipe (&wmn_reply); -#else - free (prop); -#endif - } - - if (newline_wanted) - printf ("\n"); - - return; -} - - -/* - * Display Stats on window - */ -static const binding _window_classes[] = { - { XCB_WINDOW_CLASS_INPUT_OUTPUT, "InputOutput" }, - { XCB_WINDOW_CLASS_INPUT_ONLY, "InputOnly" }, - { 0, NULL } }; - -static const binding _map_states[] = { - { XCB_MAP_STATE_UNMAPPED, "IsUnMapped" }, - { XCB_MAP_STATE_UNVIEWABLE, "IsUnviewable" }, - { XCB_MAP_STATE_VIEWABLE, "IsViewable" }, - { 0, NULL } }; - -static const binding _backing_store_states[] = { - { 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[] = { - { 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[] = { - { 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[] = { - { 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 (struct wininfo *w) -{ - 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 = (int16_t)trans_coords->dst_x; - ry = (int16_t)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_ICCCM_SIZE_HINT_P_RESIZE_INC) && - (hints.width_inc != 0) && (hints.height_inc != 0)) { - if (hints.flags & - (XCB_ICCCM_SIZE_HINT_BASE_SIZE|XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)) { - if (hints.flags & XCB_ICCCM_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_ICCCM_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"); -} - - -/* - * Display bits info: - */ -static const binding _gravities[] = { - /* 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[] = { - { XCB_BACKING_STORE_NOT_USEFUL, "NotUseful" }, - { XCB_BACKING_STORE_WHEN_MAPPED,"WhenMapped" }, - { XCB_BACKING_STORE_ALWAYS, "Always" }, - { 0, NULL } }; - -static const binding _bool[] = { - { 0, "No" }, - { 1, "Yes" }, - { 0, NULL } }; - -/* - * Requires wininfo members initialized: - * window, attr_cookie (or win_attributes) - */ -static void -Display_Bits_Info (struct wininfo * w) -{ - 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)); -} - - -/* - * Routine to display all events in an event mask - */ -static const binding _event_mask_names[] = { - { 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) -{ - 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)); -} - - -/* - * Display info on events - * - * Requires wininfo members initialized: - * window, attr_cookie (or win_attributes) - */ -static void -Display_Events_Info (struct wininfo *w) -{ - 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 (" 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)); -} - - - /* left out visual stuff */ - /* left out colormap */ - /* left out map_installed */ - - -/* - * 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 (struct wininfo *w, int recurse) -{ - display_tree_info_1 (w, recurse, 0); -} - -/* - * level - recursion level - */ -static void -display_tree_info_1 (struct wininfo *w, int recurse, int level) -{ - 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_icccm_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_icccm_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 (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 ? ":" : "."); - } - - 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_icccm_get_wm_name (dpy, child_list[i]); - cw->wm_class_cookie = xcb_icccm_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_icccm_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_icccm_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_icccm_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); - } - - free (tree); /* includes storage for child_list[] */ -} - - -/* - * Display a set of size hints - */ -static void -Display_Hints (xcb_size_hints_t *hints) -{ - long flags; - - flags = hints->flags; - - if (flags & XCB_ICCCM_SIZE_HINT_US_POSITION) - printf (" User supplied location: %s, %s\n", - xscale (hints->x), yscale (hints->y)); - - if (flags & XCB_ICCCM_SIZE_HINT_P_POSITION) - printf (" Program supplied location: %s, %s\n", - xscale (hints->x), yscale (hints->y)); - - if (flags & XCB_ICCCM_SIZE_HINT_US_SIZE) { - printf (" User supplied size: %s by %s\n", - xscale (hints->width), yscale (hints->height)); - } - - if (flags & XCB_ICCCM_SIZE_HINT_P_SIZE) - printf (" Program supplied size: %s by %s\n", - xscale (hints->width), yscale (hints->height)); - - if (flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) - printf (" Program supplied minimum size: %s by %s\n", - xscale (hints->min_width), yscale (hints->min_height)); - - if (flags & XCB_ICCCM_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_ICCCM_SIZE_HINT_BASE_SIZE) { - printf (" Program supplied base size: %s by %s\n", - xscale (hints->base_width), yscale (hints->base_height)); - } - - if (flags & XCB_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_SIZE_HINT_P_WIN_GRAVITY) { - printf (" Program supplied window gravity: %s\n", - Lookup (hints->win_gravity, _gravities)); - } -} - - -/* - * Display Size Hints info - */ -static void -Display_Size_Hints (struct wininfo *w) -{ - xcb_size_hints_t 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_icccm_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 (xcb_window_t window) -{ - 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"); - - 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; - } - - if (!extents->bounding_shaped) - printf (" No window shape defined\n"); - else { - 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 (!extents->clip_shaped) - printf (" No border shape defined\n"); - else { - 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[] = { - { XCB_ICCCM_WM_STATE_WITHDRAWN, "Withdrawn State" }, - { XCB_ICCCM_WM_STATE_NORMAL, "Normal State" }, - { XCB_ICCCM_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_icccm_get_wm_hints_reply wm_hints_reply -#endif - -static void -Display_WM_Info (struct wininfo *w) -{ - xcb_icccm_wm_hints_t wmhints; - long flags; - xcb_get_property_reply_t *prop; - int i; - - printf ("\n"); - if (!xcb_icccm_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_ICCCM_WM_HINT_INPUT) - printf (" Client accepts input or input focus: %s\n", - Lookup (wmhints.input, _bool)); - - if (flags & XCB_ICCCM_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_icccm_get_wm_name (dpy, iw.window); - - printf (" Icon window id: "); - Display_Window_Id (&iw, True); - } - - if (flags & XCB_ICCCM_WM_HINT_ICON_POSITION) - printf (" Initial icon position: %s, %s\n", - xscale (wmhints.icon_x), yscale (wmhints.icon_y)); - - if (flags & XCB_ICCCM_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); - } - } - 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); - - 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 (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); - - printf (" Frame extents: %d, %d, %d, %d\n", - extents[0], extents[1], extents[2], extents[3]); - } - free (prop); - } -} - -/* 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); -} - -/* 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; - ICONV_CONST 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; - } - - printf (format, name_start); - free (lowered_name); -} +/* + * 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 + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL +INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +*/ + + +/* + * xwininfo.c - MIT Project Athena, X Window system window + * information utility. + * + * + * This program will report all relevant information + * about a specific window. + * + * Author: Mark Lillibridge, MIT Project Athena + * 16-Jun-87 + */ + +#include "config.h" + +#include +#include +#ifdef USE_XCB_ICCCM +# include +#endif +#include + +#include +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif +#ifdef HAVE_ICONV +# include +#endif +#include +#include + +#ifndef HAVE_STRNLEN +#include "strnlen.h" +#endif + +/* Include routines to handle parsing defaults */ +#include "dsimple.h" + +typedef struct { + long code; + const char *name; +} binding; + +#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_icccm_wm_hints_t wm_hints_t + +enum { + /* xcb_size_hints_flags_t */ + XCB_ICCCM_SIZE_HINT_US_POSITION = 1 << 0, + XCB_ICCCM_SIZE_HINT_US_SIZE = 1 << 1, + XCB_ICCCM_SIZE_HINT_P_POSITION = 1 << 2, + XCB_ICCCM_SIZE_HINT_P_SIZE = 1 << 3, + XCB_ICCCM_SIZE_HINT_P_MIN_SIZE = 1 << 4, + XCB_ICCCM_SIZE_HINT_P_MAX_SIZE = 1 << 5, + XCB_ICCCM_SIZE_HINT_P_RESIZE_INC = 1 << 6, + XCB_ICCCM_SIZE_HINT_P_ASPECT = 1 << 7, + XCB_ICCCM_SIZE_HINT_BASE_SIZE = 1 << 8, + XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY = 1 << 9, + /* xcb_wm_state_t */ + XCB_ICCCM_WM_STATE_WITHDRAWN = 0, + XCB_ICCCM_WM_STATE_NORMAL = 1, + XCB_ICCCM_WM_STATE_ICONIC = 3, + /* xcb_wm_t */ + XCB_ICCCM_WM_HINT_INPUT = (1L << 0), + XCB_ICCCM_WM_HINT_STATE = (1L << 1), + XCB_ICCCM_WM_HINT_ICON_PIXMAP = (1L << 2), + XCB_ICCCM_WM_HINT_ICON_WINDOW = (1L << 3), + XCB_ICCCM_WM_HINT_ICON_POSITION = (1L << 4), + XCB_ICCCM_WM_HINT_ICON_MASK = (1L << 5), + XCB_ICCCM_WM_HINT_WINDOW_GROUP = (1L << 6), + XCB_ICCCM_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_icccm_get_wm_name(Dpy, Win) \ + GET_TEXT_PROPERTY(Dpy, Win, XCB_ATOM_WM_NAME) + +# define xcb_icccm_get_wm_class(Dpy, Win) \ + xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, BUFSIZ) +# define xcb_icccm_get_wm_hints(Dpy, Win) \ + xcb_get_property(Dpy, False, Win, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9) + +# define xcb_icccm_get_wm_size_hints(Dpy, Win, Atom) \ + xcb_get_property (Dpy, False, Win, Atom, XCB_ATOM_WM_SIZE_HINTS, 0, 18) +# define xcb_icccm_get_wm_normal_hints(Dpy, Win) \ + xcb_icccm_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) +{ + size_t sd = strlen (dst); + size_t ss = strlen (src); + size_t s = sd + ss; + + if (s < dstsize) { + strcpy (dst + sd, src); + } else { + strncpy (dst + sd, src, dstsize-sd-1); + dst[dstsize] = '\0'; + } + return s; +} +#endif + +/* + * Report the syntax for calling xwininfo: + */ +static void +usage (void) +{ + fprintf (stderr, + "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); +} + +/* + * pixel to inch, metric converter. + * Hacked in by Mark W. Eichin [eichin:19880619.1509EST] + * + * Simply put: replace the old numbers with string print calls. + * Returning a local string is ok, since we only ever get called to + * print one x and one y, so as long as they don't collide, they're + * fine. This is not meant to be a general purpose routine. + * + */ + +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 (xcb_screen_t *screen) +{ + 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) +#define YARD (3*12) +#define FOOT (12) + +static char * +nscale (int n, int np, int nmm, char *nbuf, size_t nbufsize) +{ + int s; + snprintf (nbuf, nbufsize, "%d", n); + + if (metric||english) { + s = strlcat (nbuf, " (", nbufsize); + + if (metric) { + snprintf (nbuf+s, nbufsize-s, "%.2f mm%s", + ((double) n) * nmm/np , english ? "; " : ""); + } + if (english) { + double inch_frac; + Bool printed_anything = False; + int mi, yar, ft, inr; + + inch_frac = ((double) n)*(nmm/25.4)/np; + inr = (int)inch_frac; + inch_frac -= (double)inr; + if (inr >= MILE) { + mi = inr/MILE; + inr %= MILE; + 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"); + 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"); + 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); + } + return (nbuf); +} + +static char xbuf[BUFSIZ]; +static char * +xscale (int x) +{ + return (nscale (x, xp, xmm, xbuf, sizeof(xbuf))); +} + +static char ybuf[BUFSIZ]; +static char * +yscale (int y) +{ + return (nscale (y, yp, ymm, ybuf, sizeof(ybuf))); +} + +static char bbuf[BUFSIZ]; +static char * +bscale (int b) +{ + return (nscale (b, bp, bmm, bbuf, sizeof(bbuf))); +} + +/* end of pixel to inch, metric converter */ + +int +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; + 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 + 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 (); + } + + 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"); + } + /* 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 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); + } + + /* + * 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); + } + } + + /* 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_icccm_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 (stats || bits || events) + w->attr_cookie = xcb_get_window_attributes (dpy, window); + if (stats || size) + w->normal_hints_cookie = xcb_icccm_get_wm_normal_hints (dpy, window); + if (wm) { + w->hints_cookie = xcb_icccm_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 = xcb_get_property + (dpy, False, window, XCB_ATOM_WM_CLIENT_MACHINE, + XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ); + } + + 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 (size) + w->zoom_cookie = xcb_icccm_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); + } +#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."); + } + } + 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; + } + + 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_icccm_get_wm_normal_hints_reply wm_size_hints_reply +#define xcb_icccm_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_icccm_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)); + } + } + if (hints_return && w->normal_hints) + memcpy(hints_return, w->normal_hints, sizeof(xcb_size_hints_t)); + return w->normal_hints; +} + + +/* + * Lookup: lookup a code in a table. + */ +static char _lookup_buffer[100]; + +static const char * +LookupL (long code, const binding *table) +{ + const char *name = NULL; + + 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); +} + +static const char * +Lookup (int code, const binding *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 (struct wininfo *w, Bool newline_wanted) +{ +#ifdef USE_XCB_ICCCM + xcb_icccm_get_text_property_reply_t wmn_reply; + uint8_t got_reply = False; +#endif + xcb_get_property_reply_t *prop; + const char *wm_name = NULL; + unsigned int wm_name_len = 0; + xcb_atom_t wm_name_encoding = XCB_NONE; + + printf (window_id_format, w->window); /* print id # in hex/dec */ + + if (!w->window) { + printf (" (none)"); + } else { + if (w->window == screen->root) { + printf (" (the root window)"); + } + /* 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; + } else { /* No _NET_WM_NAME, check WM_NAME */ +#ifdef USE_XCB_ICCCM + got_reply = xcb_icccm_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 + 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; + } +#endif + } + if (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_icccm_get_text_property_reply_wipe (&wmn_reply); +#else + free (prop); +#endif + } + + if (newline_wanted) + printf ("\n"); + + return; +} + + +/* + * Display Stats on window + */ +static const binding _window_classes[] = { + { XCB_WINDOW_CLASS_INPUT_OUTPUT, "InputOutput" }, + { XCB_WINDOW_CLASS_INPUT_ONLY, "InputOnly" }, + { 0, NULL } }; + +static const binding _map_states[] = { + { XCB_MAP_STATE_UNMAPPED, "IsUnMapped" }, + { XCB_MAP_STATE_UNVIEWABLE, "IsUnviewable" }, + { XCB_MAP_STATE_VIEWABLE, "IsViewable" }, + { 0, NULL } }; + +static const binding _backing_store_states[] = { + { 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[] = { + { 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[] = { + { 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[] = { + { 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 (struct wininfo *w) +{ + 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 = (int16_t)trans_coords->dst_x; + ry = (int16_t)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_ICCCM_SIZE_HINT_P_RESIZE_INC) && + (hints.width_inc != 0) && (hints.height_inc != 0)) { + if (hints.flags & + (XCB_ICCCM_SIZE_HINT_BASE_SIZE|XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)) { + if (hints.flags & XCB_ICCCM_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_ICCCM_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"); +} + + +/* + * Display bits info: + */ +static const binding _gravities[] = { + /* 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[] = { + { XCB_BACKING_STORE_NOT_USEFUL, "NotUseful" }, + { XCB_BACKING_STORE_WHEN_MAPPED,"WhenMapped" }, + { XCB_BACKING_STORE_ALWAYS, "Always" }, + { 0, NULL } }; + +static const binding _bool[] = { + { 0, "No" }, + { 1, "Yes" }, + { 0, NULL } }; + +/* + * Requires wininfo members initialized: + * window, attr_cookie (or win_attributes) + */ +static void +Display_Bits_Info (struct wininfo * w) +{ + 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)); +} + + +/* + * Routine to display all events in an event mask + */ +static const binding _event_mask_names[] = { + { 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) +{ + 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)); +} + + +/* + * Display info on events + * + * Requires wininfo members initialized: + * window, attr_cookie (or win_attributes) + */ +static void +Display_Events_Info (struct wininfo *w) +{ + 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 (" 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)); +} + + + /* left out visual stuff */ + /* left out colormap */ + /* left out map_installed */ + + +/* + * 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 (struct wininfo *w, int recurse) +{ + display_tree_info_1 (w, recurse, 0); +} + +/* + * level - recursion level + */ +static void +display_tree_info_1 (struct wininfo *w, int recurse, int level) +{ + 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_icccm_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_icccm_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 (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 ? ":" : "."); + } + + 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_icccm_get_wm_name (dpy, child_list[i]); + cw->wm_class_cookie = xcb_icccm_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_icccm_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_icccm_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_icccm_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); + } + + free (tree); /* includes storage for child_list[] */ +} + + +/* + * Display a set of size hints + */ +static void +Display_Hints (xcb_size_hints_t *hints) +{ + long flags; + + flags = hints->flags; + + if (flags & XCB_ICCCM_SIZE_HINT_US_POSITION) + printf (" User supplied location: %s, %s\n", + xscale (hints->x), yscale (hints->y)); + + if (flags & XCB_ICCCM_SIZE_HINT_P_POSITION) + printf (" Program supplied location: %s, %s\n", + xscale (hints->x), yscale (hints->y)); + + if (flags & XCB_ICCCM_SIZE_HINT_US_SIZE) { + printf (" User supplied size: %s by %s\n", + xscale (hints->width), yscale (hints->height)); + } + + if (flags & XCB_ICCCM_SIZE_HINT_P_SIZE) + printf (" Program supplied size: %s by %s\n", + xscale (hints->width), yscale (hints->height)); + + if (flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) + printf (" Program supplied minimum size: %s by %s\n", + xscale (hints->min_width), yscale (hints->min_height)); + + if (flags & XCB_ICCCM_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_ICCCM_SIZE_HINT_BASE_SIZE) { + printf (" Program supplied base size: %s by %s\n", + xscale (hints->base_width), yscale (hints->base_height)); + } + + if (flags & XCB_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_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_ICCCM_SIZE_HINT_P_WIN_GRAVITY) { + printf (" Program supplied window gravity: %s\n", + Lookup (hints->win_gravity, _gravities)); + } +} + + +/* + * Display Size Hints info + */ +static void +Display_Size_Hints (struct wininfo *w) +{ + xcb_size_hints_t 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_icccm_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 (xcb_window_t window) +{ + 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"); + + 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; + } + + if (!extents->bounding_shaped) + printf (" No window shape defined\n"); + else { + 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 (!extents->clip_shaped) + printf (" No border shape defined\n"); + else { + 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[] = { + { XCB_ICCCM_WM_STATE_WITHDRAWN, "Withdrawn State" }, + { XCB_ICCCM_WM_STATE_NORMAL, "Normal State" }, + { XCB_ICCCM_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_icccm_get_wm_hints_reply wm_hints_reply +#endif + +static void +Display_WM_Info (struct wininfo *w) +{ + xcb_icccm_wm_hints_t wmhints; + long flags; + xcb_get_property_reply_t *prop; + int i; + + printf ("\n"); + if (!xcb_icccm_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_ICCCM_WM_HINT_INPUT) + printf (" Client accepts input or input focus: %s\n", + Lookup (wmhints.input, _bool)); + + if (flags & XCB_ICCCM_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_icccm_get_wm_name (dpy, iw.window); + + printf (" Icon window id: "); + Display_Window_Id (&iw, True); + } + + if (flags & XCB_ICCCM_WM_HINT_ICON_POSITION) + printf (" Initial icon position: %s, %s\n", + xscale (wmhints.icon_x), yscale (wmhints.icon_y)); + + if (flags & XCB_ICCCM_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); + } + } + 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); + + 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 (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); + + printf (" Frame extents: %d, %d, %d, %d\n", + extents[0], extents[1], extents[2], extents[3]); + } + free (prop); + } +} + +/* 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); +} + +/* 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; + ICONV_CONST 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; + } + + printf (format, name_start); + free (lowered_name); +} -- cgit v1.2.3