xwininfo.c revision e8f4a63f
1863f95b1Smrg/* 2863f95b1Smrg * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 3863f95b1Smrg * 4863f95b1Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5863f95b1Smrg * copy of this software and associated documentation files (the "Software"), 6863f95b1Smrg * to deal in the Software without restriction, including without limitation 7863f95b1Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8863f95b1Smrg * and/or sell copies of the Software, and to permit persons to whom the 9863f95b1Smrg * Software is furnished to do so, subject to the following conditions: 10863f95b1Smrg * 11863f95b1Smrg * The above copyright notice and this permission notice (including the next 12863f95b1Smrg * paragraph) shall be included in all copies or substantial portions of the 13863f95b1Smrg * Software. 14863f95b1Smrg * 15863f95b1Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16863f95b1Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17863f95b1Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18863f95b1Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19863f95b1Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20863f95b1Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21863f95b1Smrg * DEALINGS IN THE SOFTWARE. 22863f95b1Smrg */ 23ff7e0accSmrg/* 24ff7e0accSmrg 25ff7e0accSmrgCopyright 1987, 1998 The Open Group 26ff7e0accSmrg 27ff7e0accSmrgPermission to use, copy, modify, distribute, and sell this software and its 28ff7e0accSmrgdocumentation for any purpose is hereby granted without fee, provided that 29ff7e0accSmrgthe above copyright notice appear in all copies and that both that 30ff7e0accSmrgcopyright notice and this permission notice appear in supporting 31ff7e0accSmrgdocumentation. 32ff7e0accSmrg 33ff7e0accSmrgThe above copyright notice and this permission notice shall be included 34ff7e0accSmrgin all copies or substantial portions of the Software. 35ff7e0accSmrg 36ff7e0accSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 37ff7e0accSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 38ff7e0accSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 39ff7e0accSmrgOF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 40ff7e0accSmrgHOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 41ff7e0accSmrgINDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 42ff7e0accSmrgFROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 43ff7e0accSmrgNEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 44ff7e0accSmrgWITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 45ff7e0accSmrg 46ff7e0accSmrgExcept as contained in this notice, the name of a copyright holder 47ff7e0accSmrgshall not be used in advertising or otherwise to promote the sale, use 48ff7e0accSmrgor other dealings in this Software without prior written authorization 49ff7e0accSmrgof the copyright holder. 50ff7e0accSmrg 51ff7e0accSmrg*/ 52ff7e0accSmrg 53ff7e0accSmrg 54ff7e0accSmrg/* 55ff7e0accSmrg * xwininfo.c - MIT Project Athena, X Window system window 56ff7e0accSmrg * information utility. 57ff7e0accSmrg * 58ff7e0accSmrg * 59ff7e0accSmrg * This program will report all relevant information 60ff7e0accSmrg * about a specific window. 61ff7e0accSmrg * 62ff7e0accSmrg * Author: Mark Lillibridge, MIT Project Athena 63ff7e0accSmrg * 16-Jun-87 64ff7e0accSmrg */ 65ff7e0accSmrg 66ff7e0accSmrg#include "config.h" 67863f95b1Smrg 68863f95b1Smrg#include <xcb/xcb.h> 69863f95b1Smrg#include <xcb/xproto.h> 70863f95b1Smrg#ifdef USE_XCB_ICCCM 71863f95b1Smrg# include <xcb/xcb_icccm.h> 72ff7e0accSmrg#endif 73863f95b1Smrg#include <xcb/shape.h> 74863f95b1Smrg 75ff7e0accSmrg#include <stdio.h> 76ff7e0accSmrg#include <stdlib.h> 77863f95b1Smrg#include <string.h> 78863f95b1Smrg#include <locale.h> 79863f95b1Smrg#include <langinfo.h> 80863f95b1Smrg#ifdef HAVE_ICONV 81863f95b1Smrg# include <iconv.h> 82863f95b1Smrg#endif 83863f95b1Smrg#include <ctype.h> 84863f95b1Smrg#include <errno.h> 85863f95b1Smrg 86863f95b1Smrg#ifndef HAVE_STRNLEN 87863f95b1Smrg#include "strnlen.h" 88863f95b1Smrg#endif 89ff7e0accSmrg 90ff7e0accSmrg/* Include routines to handle parsing defaults */ 91ff7e0accSmrg#include "dsimple.h" 92ff7e0accSmrg 93ff7e0accSmrgtypedef struct { 94863f95b1Smrg long code; 95863f95b1Smrg const char *name; 96ff7e0accSmrg} binding; 97ff7e0accSmrg 98863f95b1Smrg#ifndef USE_XCB_ICCCM 99863f95b1Smrg/* Once xcb-icccm's API is stable, this should be replaced by 100863f95b1Smrg xcb_size_hints_t & xcb_size_hints_flags_t */ 101863f95b1Smrgtypedef struct { 102863f95b1Smrg /** User specified flags */ 103863f95b1Smrg uint32_t flags; 104863f95b1Smrg /** User-specified position */ 105863f95b1Smrg int32_t x, y; 106863f95b1Smrg /** User-specified size */ 107863f95b1Smrg int32_t width, height; 108863f95b1Smrg /** Program-specified minimum size */ 109863f95b1Smrg int32_t min_width, min_height; 110863f95b1Smrg /** Program-specified maximum size */ 111863f95b1Smrg int32_t max_width, max_height; 112863f95b1Smrg /** Program-specified resize increments */ 113863f95b1Smrg int32_t width_inc, height_inc; 114863f95b1Smrg /** Program-specified minimum aspect ratios */ 115863f95b1Smrg int32_t min_aspect_num, min_aspect_den; 116863f95b1Smrg /** Program-specified maximum aspect ratios */ 117863f95b1Smrg int32_t max_aspect_num, max_aspect_den; 118863f95b1Smrg /** Program-specified base size */ 119863f95b1Smrg int32_t base_width, base_height; 120863f95b1Smrg /** Program-specified window gravity */ 121863f95b1Smrg uint32_t win_gravity; 122863f95b1Smrg} wm_size_hints_t; 123863f95b1Smrg 124863f95b1Smrg# define xcb_size_hints_t wm_size_hints_t 125863f95b1Smrg 126863f95b1Smrgtypedef struct { 127863f95b1Smrg /** Marks which fields in this structure are defined */ 128863f95b1Smrg int32_t flags; 129863f95b1Smrg /** Does this application rely on the window manager to get keyboard 130863f95b1Smrg input? */ 131863f95b1Smrg uint32_t input; 132863f95b1Smrg /** See below */ 133863f95b1Smrg int32_t initial_state; 134863f95b1Smrg /** Pixmap to be used as icon */ 135863f95b1Smrg xcb_pixmap_t icon_pixmap; 136863f95b1Smrg /** Window to be used as icon */ 137863f95b1Smrg xcb_window_t icon_window; 138863f95b1Smrg /** Initial position of icon */ 139863f95b1Smrg int32_t icon_x, icon_y; 140863f95b1Smrg /** Icon mask bitmap */ 141863f95b1Smrg xcb_pixmap_t icon_mask; 142863f95b1Smrg /* Identifier of related window group */ 143863f95b1Smrg xcb_window_t window_group; 144863f95b1Smrg} wm_hints_t; 145863f95b1Smrg 146853aa076Smrg#define xcb_icccm_wm_hints_t wm_hints_t 147863f95b1Smrg 148863f95b1Smrgenum { 149863f95b1Smrg /* xcb_size_hints_flags_t */ 150853aa076Smrg XCB_ICCCM_SIZE_HINT_US_POSITION = 1 << 0, 151853aa076Smrg XCB_ICCCM_SIZE_HINT_US_SIZE = 1 << 1, 152853aa076Smrg XCB_ICCCM_SIZE_HINT_P_POSITION = 1 << 2, 153853aa076Smrg XCB_ICCCM_SIZE_HINT_P_SIZE = 1 << 3, 154853aa076Smrg XCB_ICCCM_SIZE_HINT_P_MIN_SIZE = 1 << 4, 155853aa076Smrg XCB_ICCCM_SIZE_HINT_P_MAX_SIZE = 1 << 5, 156853aa076Smrg XCB_ICCCM_SIZE_HINT_P_RESIZE_INC = 1 << 6, 157853aa076Smrg XCB_ICCCM_SIZE_HINT_P_ASPECT = 1 << 7, 158853aa076Smrg XCB_ICCCM_SIZE_HINT_BASE_SIZE = 1 << 8, 159853aa076Smrg XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY = 1 << 9, 160863f95b1Smrg /* xcb_wm_state_t */ 161853aa076Smrg XCB_ICCCM_WM_STATE_WITHDRAWN = 0, 162853aa076Smrg XCB_ICCCM_WM_STATE_NORMAL = 1, 163853aa076Smrg XCB_ICCCM_WM_STATE_ICONIC = 3, 164863f95b1Smrg /* xcb_wm_t */ 165853aa076Smrg XCB_ICCCM_WM_HINT_INPUT = (1L << 0), 166853aa076Smrg XCB_ICCCM_WM_HINT_STATE = (1L << 1), 167853aa076Smrg XCB_ICCCM_WM_HINT_ICON_PIXMAP = (1L << 2), 168853aa076Smrg XCB_ICCCM_WM_HINT_ICON_WINDOW = (1L << 3), 169853aa076Smrg XCB_ICCCM_WM_HINT_ICON_POSITION = (1L << 4), 170853aa076Smrg XCB_ICCCM_WM_HINT_ICON_MASK = (1L << 5), 171853aa076Smrg XCB_ICCCM_WM_HINT_WINDOW_GROUP = (1L << 6), 172853aa076Smrg XCB_ICCCM_WM_HINT_X_URGENCY = (1L << 8) 173863f95b1Smrg}; 174863f95b1Smrg 175863f95b1Smrg/* Once xcb-icccm's API is stable, these should be replaced by calls to it */ 176863f95b1Smrg# define GET_TEXT_PROPERTY(Dpy, Win, Atom) \ 177863f95b1Smrg xcb_get_property (Dpy, False, Win, Atom, XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ) 178853aa076Smrg# define xcb_icccm_get_wm_name(Dpy, Win) \ 179853aa076Smrg GET_TEXT_PROPERTY(Dpy, Win, XCB_ATOM_WM_NAME) 180863f95b1Smrg 181853aa076Smrg# define xcb_icccm_get_wm_class(Dpy, Win) \ 182863f95b1Smrg xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, BUFSIZ) 183853aa076Smrg# define xcb_icccm_get_wm_hints(Dpy, Win) \ 184863f95b1Smrg xcb_get_property(Dpy, False, Win, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9) 185863f95b1Smrg 186853aa076Smrg# define xcb_icccm_get_wm_size_hints(Dpy, Win, Atom) \ 187863f95b1Smrg xcb_get_property (Dpy, False, Win, Atom, XCB_ATOM_WM_SIZE_HINTS, 0, 18) 188853aa076Smrg# define xcb_icccm_get_wm_normal_hints(Dpy, Win) \ 189853aa076Smrg xcb_icccm_get_wm_size_hints(Dpy, Win, XCB_ATOM_WM_NORMAL_HINTS) 190863f95b1Smrg#endif 191863f95b1Smrg 192863f95b1Smrg/* Possibly in xcb-emwh in the future? */ 193863f95b1Smrgstatic xcb_atom_t atom_net_wm_name, atom_utf8_string; 194863f95b1Smrgstatic xcb_atom_t atom_net_wm_desktop, atom_net_wm_window_type, 195863f95b1Smrg atom_net_wm_state, atom_net_wm_pid, atom_net_frame_extents; 196863f95b1Smrgstatic xcb_get_property_cookie_t get_net_wm_name (xcb_connection_t *, 197863f95b1Smrg xcb_window_t); 198863f95b1Smrg 199863f95b1Smrg/* Information we keep track of for each window to allow prefetching/reusing */ 200863f95b1Smrgstruct wininfo { 201863f95b1Smrg xcb_window_t window; 202863f95b1Smrg 203863f95b1Smrg /* cookies for requests we've sent */ 204863f95b1Smrg xcb_get_geometry_cookie_t geometry_cookie; 205863f95b1Smrg xcb_get_property_cookie_t net_wm_name_cookie; 206863f95b1Smrg xcb_get_property_cookie_t wm_name_cookie; 207863f95b1Smrg xcb_get_property_cookie_t wm_class_cookie; 208863f95b1Smrg xcb_translate_coordinates_cookie_t trans_coords_cookie; 209863f95b1Smrg xcb_query_tree_cookie_t tree_cookie; 210863f95b1Smrg xcb_get_window_attributes_cookie_t attr_cookie; 211863f95b1Smrg xcb_get_property_cookie_t normal_hints_cookie; 212863f95b1Smrg xcb_get_property_cookie_t hints_cookie; 213863f95b1Smrg xcb_get_property_cookie_t wm_desktop_cookie; 214863f95b1Smrg xcb_get_property_cookie_t wm_window_type_cookie; 215863f95b1Smrg xcb_get_property_cookie_t wm_state_cookie; 216863f95b1Smrg xcb_get_property_cookie_t wm_pid_cookie; 217863f95b1Smrg xcb_get_property_cookie_t wm_client_machine_cookie; 218863f95b1Smrg xcb_get_property_cookie_t frame_extents_cookie; 219863f95b1Smrg xcb_get_property_cookie_t zoom_cookie; 220863f95b1Smrg 221863f95b1Smrg /* cached results from previous requests */ 222863f95b1Smrg xcb_get_geometry_reply_t * geometry; 223863f95b1Smrg xcb_get_window_attributes_reply_t * win_attributes; 224863f95b1Smrg xcb_size_hints_t * normal_hints; 225863f95b1Smrg}; 226863f95b1Smrg 227863f95b1Smrgstatic void scale_init (xcb_screen_t *scrn); 228863f95b1Smrgstatic char *nscale (int, int, int, char *, size_t); 229863f95b1Smrgstatic char *xscale (int); 230863f95b1Smrgstatic char *yscale (int); 231863f95b1Smrgstatic char *bscale (int); 232863f95b1Smrgint main (int, char **); 233863f95b1Smrgstatic const char *LookupL (long, const binding *); 234863f95b1Smrgstatic const char *Lookup (int, const binding *); 235863f95b1Smrgstatic void Display_Window_Id (struct wininfo *, Bool); 236863f95b1Smrgstatic void Display_Stats_Info (struct wininfo *); 237863f95b1Smrgstatic void Display_Bits_Info (struct wininfo *); 238863f95b1Smrgstatic void Display_Event_Mask (long); 239863f95b1Smrgstatic void Display_Events_Info (struct wininfo *); 240863f95b1Smrgstatic void Display_Tree_Info (struct wininfo *, int); 241863f95b1Smrgstatic void display_tree_info_1 (struct wininfo *, int, int); 242863f95b1Smrgstatic void Display_Hints (xcb_size_hints_t *); 243863f95b1Smrgstatic void Display_Size_Hints (struct wininfo *); 244863f95b1Smrgstatic void Display_Window_Shape (xcb_window_t); 245863f95b1Smrgstatic void Display_WM_Info (struct wininfo *); 246863f95b1Smrgstatic void wininfo_wipe (struct wininfo *); 247863f95b1Smrg 248cf2cd791Smrgstatic Bool window_id_format_dec = False; 249863f95b1Smrg 250863f95b1Smrg#ifdef HAVE_ICONV 251863f95b1Smrgstatic iconv_t iconv_from_utf8; 252863f95b1Smrg#endif 253863f95b1Smrgstatic const char *user_encoding; 254cf2cd791Smrgstatic void print_utf8 (const char *, const char *, size_t, const char *); 255cf2cd791Smrgstatic char *get_friendly_name (const char *, const char *); 256863f95b1Smrg 257863f95b1Smrgstatic xcb_connection_t *dpy; 258863f95b1Smrgstatic xcb_screen_t *screen; 259863f95b1Smrgstatic xcb_generic_error_t *err; 260ff7e0accSmrg 261ff7e0accSmrg#ifndef HAVE_STRLCAT 262863f95b1Smrgstatic size_t strlcat (char *dst, const char *src, size_t dstsize) 263ff7e0accSmrg{ 264863f95b1Smrg size_t sd = strlen (dst); 265863f95b1Smrg size_t ss = strlen (src); 266ff7e0accSmrg size_t s = sd + ss; 267863f95b1Smrg 268ff7e0accSmrg if (s < dstsize) { 269863f95b1Smrg strcpy (dst + sd, src); 270ff7e0accSmrg } else { 271863f95b1Smrg strncpy (dst + sd, src, dstsize-sd-1); 272ff7e0accSmrg dst[dstsize] = '\0'; 273ff7e0accSmrg } 274ff7e0accSmrg return s; 275ff7e0accSmrg} 276ff7e0accSmrg#endif 277ff7e0accSmrg 278ff7e0accSmrg/* 279ff7e0accSmrg * Report the syntax for calling xwininfo: 280ff7e0accSmrg */ 28196eca5d1Smrg_X_NORETURN _X_COLD 282853aa076Smrgstatic void 283863f95b1Smrgusage (void) 284ff7e0accSmrg{ 285ff7e0accSmrg fprintf (stderr, 286863f95b1Smrg "usage: %s [-options ...]\n\n" 287863f95b1Smrg "where options include:\n" 288e8f4a63fSmrg " -help print this message\n" 289e8f4a63fSmrg " -version print version message\n" 290e8f4a63fSmrg " -d[isplay] <host:dpy> X server to contact\n" 291e8f4a63fSmrg " -root use the root window\n" 292e8f4a63fSmrg " -id <wdid> use the window with the specified id\n" 293e8f4a63fSmrg " -name <wdname> use the window with the specified name\n" 294e8f4a63fSmrg " -int print window id in decimal\n" 295e8f4a63fSmrg " -children print parent and child identifiers\n" 296e8f4a63fSmrg " -tree print children identifiers recursively\n" 297e8f4a63fSmrg " -stats print window geometry [DEFAULT]\n" 298e8f4a63fSmrg " -bits print window pixel information\n" 299e8f4a63fSmrg " -events print events selected for on window\n" 300e8f4a63fSmrg " -size print size hints\n" 301e8f4a63fSmrg " -wm print window manager hints\n" 302e8f4a63fSmrg " -shape print shape extents\n" 303e8f4a63fSmrg " -frame don't ignore window manager frames\n" 304e8f4a63fSmrg " -english print sizes in english units\n" 305e8f4a63fSmrg " -metric print sizes in metric units\n" 306e8f4a63fSmrg " -all -tree, -stats, -bits, -events, -wm, -size, -shape\n" 307863f95b1Smrg "\n", 308863f95b1Smrg program_name); 309ff7e0accSmrg exit (1); 310ff7e0accSmrg} 311ff7e0accSmrg 312ff7e0accSmrg/* 313ff7e0accSmrg * pixel to inch, metric converter. 314ff7e0accSmrg * Hacked in by Mark W. Eichin <eichin@athena> [eichin:19880619.1509EST] 315ff7e0accSmrg * 316ff7e0accSmrg * Simply put: replace the old numbers with string print calls. 317ff7e0accSmrg * Returning a local string is ok, since we only ever get called to 318ff7e0accSmrg * print one x and one y, so as long as they don't collide, they're 319ff7e0accSmrg * fine. This is not meant to be a general purpose routine. 320ff7e0accSmrg * 321ff7e0accSmrg */ 322ff7e0accSmrg 323863f95b1Smrgstatic int xp = 0, xmm = 0; 324863f95b1Smrgstatic int yp = 0, ymm = 0; 325863f95b1Smrgstatic int bp = 0, bmm = 0; 326ff7e0accSmrgstatic int english = 0, metric = 0; 327ff7e0accSmrg 328ff7e0accSmrgstatic void 329cf2cd791Smrgscale_init (xcb_screen_t *scale_screen) 330ff7e0accSmrg{ 331cf2cd791Smrg xp = scale_screen->width_in_pixels; 332cf2cd791Smrg yp = scale_screen->height_in_pixels; 333cf2cd791Smrg xmm = scale_screen->width_in_millimeters; 334cf2cd791Smrg ymm = scale_screen->height_in_millimeters; 335863f95b1Smrg bp = xp + yp; 336863f95b1Smrg bmm = xmm + ymm; 337ff7e0accSmrg} 338ff7e0accSmrg 339ff7e0accSmrg#define MILE (5280*12) 340ff7e0accSmrg#define YARD (3*12) 341ff7e0accSmrg#define FOOT (12) 342ff7e0accSmrg 343ff7e0accSmrgstatic char * 344863f95b1Smrgnscale (int n, int np, int nmm, char *nbuf, size_t nbufsize) 345ff7e0accSmrg{ 346ff7e0accSmrg int s; 347863f95b1Smrg snprintf (nbuf, nbufsize, "%d", n); 348863f95b1Smrg 349ff7e0accSmrg if (metric||english) { 350863f95b1Smrg s = strlcat (nbuf, " (", nbufsize); 351ff7e0accSmrg 352ff7e0accSmrg if (metric) { 353863f95b1Smrg snprintf (nbuf+s, nbufsize-s, "%.2f mm%s", 354863f95b1Smrg ((double) n) * nmm/np , english ? "; " : ""); 355ff7e0accSmrg } 356ff7e0accSmrg if (english) { 357ff7e0accSmrg double inch_frac; 358ff7e0accSmrg Bool printed_anything = False; 359ff7e0accSmrg int mi, yar, ft, inr; 360ff7e0accSmrg 361ff7e0accSmrg inch_frac = ((double) n)*(nmm/25.4)/np; 362ff7e0accSmrg inr = (int)inch_frac; 363ff7e0accSmrg inch_frac -= (double)inr; 364ff7e0accSmrg if (inr >= MILE) { 365ff7e0accSmrg mi = inr/MILE; 366ff7e0accSmrg inr %= MILE; 367863f95b1Smrg s = strlen (nbuf); 368863f95b1Smrg snprintf (nbuf+s, nbufsize-s, "%d %s(?!?)", 369863f95b1Smrg mi, (mi == 1) ? "mile" : "miles"); 370ff7e0accSmrg printed_anything = True; 371ff7e0accSmrg } 372ff7e0accSmrg if (inr >= YARD) { 373ff7e0accSmrg yar = inr/YARD; 374ff7e0accSmrg inr %= YARD; 375ff7e0accSmrg if (printed_anything) 376863f95b1Smrg strlcat (nbuf, ", ", nbufsize); 377863f95b1Smrg s = strlen (nbuf); 378863f95b1Smrg snprintf (nbuf+s, nbufsize-s, "%d %s", 379863f95b1Smrg yar, (yar==1) ? "yard" : "yards"); 380ff7e0accSmrg printed_anything = True; 381ff7e0accSmrg } 382ff7e0accSmrg if (inr >= FOOT) { 383ff7e0accSmrg ft = inr/FOOT; 384ff7e0accSmrg inr %= FOOT; 385ff7e0accSmrg if (printed_anything) 386863f95b1Smrg strlcat (nbuf, ", ", nbufsize); 387863f95b1Smrg s = strlen (nbuf); 388863f95b1Smrg snprintf (nbuf+s, nbufsize-s, "%d %s", 389863f95b1Smrg ft, (ft==1) ? "foot" : "feet"); 390ff7e0accSmrg printed_anything = True; 391ff7e0accSmrg } 392ff7e0accSmrg if (!printed_anything || inch_frac != 0.0 || inr != 0) { 393ff7e0accSmrg if (printed_anything) 394863f95b1Smrg strlcat (nbuf, ", ", nbufsize); 395863f95b1Smrg s = strlen (nbuf); 396863f95b1Smrg snprintf (nbuf+s, nbufsize-s, "%.2f inches", inr+inch_frac); 397ff7e0accSmrg } 398ff7e0accSmrg } 399ff7e0accSmrg strlcat (nbuf, ")", nbufsize); 400ff7e0accSmrg } 401863f95b1Smrg return (nbuf); 402863f95b1Smrg} 403863f95b1Smrg 404ff7e0accSmrgstatic char xbuf[BUFSIZ]; 405ff7e0accSmrgstatic char * 406863f95b1Smrgxscale (int x) 407ff7e0accSmrg{ 408863f95b1Smrg return (nscale (x, xp, xmm, xbuf, sizeof(xbuf))); 409ff7e0accSmrg} 410ff7e0accSmrg 411ff7e0accSmrgstatic char ybuf[BUFSIZ]; 412ff7e0accSmrgstatic char * 413863f95b1Smrgyscale (int y) 414ff7e0accSmrg{ 415863f95b1Smrg return (nscale (y, yp, ymm, ybuf, sizeof(ybuf))); 416ff7e0accSmrg} 417ff7e0accSmrg 418ff7e0accSmrgstatic char bbuf[BUFSIZ]; 419ff7e0accSmrgstatic char * 420863f95b1Smrgbscale (int b) 421ff7e0accSmrg{ 422863f95b1Smrg return (nscale (b, bp, bmm, bbuf, sizeof(bbuf))); 423ff7e0accSmrg} 424ff7e0accSmrg 425cf2cd791Smrgstatic const char * 426cf2cd791Smrgwindow_id_str (xcb_window_t id) 427cf2cd791Smrg{ 428cf2cd791Smrg static char str[20]; 429cf2cd791Smrg 430cf2cd791Smrg if (window_id_format_dec) 431cf2cd791Smrg snprintf (str, sizeof(str), "%u", id); 432cf2cd791Smrg else 433cf2cd791Smrg snprintf (str, sizeof(str), "0x%x", id); 434cf2cd791Smrg 435cf2cd791Smrg return str; 436cf2cd791Smrg} 437cf2cd791Smrg 438ff7e0accSmrg/* end of pixel to inch, metric converter */ 439ff7e0accSmrg 440863f95b1Smrgint 441863f95b1Smrgmain (int argc, char **argv) 442ff7e0accSmrg{ 443863f95b1Smrg register int i; 444863f95b1Smrg int tree = 0, stats = 0, bits = 0, events = 0, wm = 0, size = 0, shape = 0; 445863f95b1Smrg int frame = 0, children = 0; 446863f95b1Smrg int use_root = 0; 447863f95b1Smrg xcb_window_t window = 0; 448863f95b1Smrg char *display_name = NULL; 449863f95b1Smrg const char *window_name = NULL; 450863f95b1Smrg struct wininfo wininfo; 451863f95b1Smrg struct wininfo *w = &wininfo; 452863f95b1Smrg 453863f95b1Smrg program_name = argv[0]; 454863f95b1Smrg 455863f95b1Smrg if (!setlocale (LC_ALL, "")) 456863f95b1Smrg fprintf (stderr, "%s: can not set locale properly\n", program_name); 457863f95b1Smrg user_encoding = nl_langinfo (CODESET); 458863f95b1Smrg if (user_encoding == NULL) 459863f95b1Smrg user_encoding = "unknown encoding"; 460863f95b1Smrg 461863f95b1Smrg memset (w, 0, sizeof(struct wininfo)); 462863f95b1Smrg 463863f95b1Smrg /* Handle our command line arguments */ 464863f95b1Smrg for (i = 1; i < argc; i++) { 465863f95b1Smrg if (!strcmp (argv[i], "-help")) 466863f95b1Smrg usage (); 467863f95b1Smrg if (!strcmp (argv[i], "-display") || !strcmp (argv[i], "-d")) { 468863f95b1Smrg if (++i >= argc) 469863f95b1Smrg Fatal_Error("-display requires argument"); 470863f95b1Smrg display_name = argv[i]; 471863f95b1Smrg continue; 472863f95b1Smrg } 473863f95b1Smrg if (!strcmp (argv[i], "-root")) { 474863f95b1Smrg use_root = 1; 475863f95b1Smrg continue; 476863f95b1Smrg } 477863f95b1Smrg if (!strcmp (argv[i], "-id")) { 478863f95b1Smrg if (++i >= argc) 479863f95b1Smrg Fatal_Error("-id requires argument"); 480863f95b1Smrg window = strtoul(argv[i], NULL, 0); 481863f95b1Smrg continue; 482863f95b1Smrg } 483863f95b1Smrg if (!strcmp (argv[i], "-name")) { 484863f95b1Smrg if (++i >= argc) 485863f95b1Smrg Fatal_Error("-name requires argument"); 486863f95b1Smrg window_name = argv[i]; 487863f95b1Smrg continue; 488863f95b1Smrg } 489863f95b1Smrg if (!strcmp (argv[i], "-int")) { 490cf2cd791Smrg window_id_format_dec = True; 491863f95b1Smrg continue; 492863f95b1Smrg } 493863f95b1Smrg if (!strcmp (argv[i], "-children")) { 494863f95b1Smrg children = 1; 495863f95b1Smrg continue; 496863f95b1Smrg } 497863f95b1Smrg if (!strcmp (argv[i], "-tree")) { 498863f95b1Smrg tree = 1; 499863f95b1Smrg continue; 500863f95b1Smrg } 501863f95b1Smrg if (!strcmp (argv[i], "-stats")) { 502863f95b1Smrg stats = 1; 503863f95b1Smrg continue; 504863f95b1Smrg } 505863f95b1Smrg if (!strcmp (argv[i], "-bits")) { 506863f95b1Smrg bits = 1; 507863f95b1Smrg continue; 508863f95b1Smrg } 509863f95b1Smrg if (!strcmp (argv[i], "-events")) { 510863f95b1Smrg events = 1; 511863f95b1Smrg continue; 512863f95b1Smrg } 513863f95b1Smrg if (!strcmp (argv[i], "-wm")) { 514863f95b1Smrg wm = 1; 515863f95b1Smrg continue; 516863f95b1Smrg } 517863f95b1Smrg if (!strcmp (argv[i], "-frame")) { 518863f95b1Smrg frame = 1; 519863f95b1Smrg continue; 520863f95b1Smrg } 521863f95b1Smrg if (!strcmp (argv[i], "-size")) { 522863f95b1Smrg size = 1; 523863f95b1Smrg continue; 524863f95b1Smrg } 525863f95b1Smrg if (!strcmp (argv[i], "-shape")) { 526863f95b1Smrg shape = 1; 527863f95b1Smrg continue; 528863f95b1Smrg } 529863f95b1Smrg if (!strcmp (argv[i], "-english")) { 530863f95b1Smrg english = 1; 531863f95b1Smrg continue; 532863f95b1Smrg } 533863f95b1Smrg if (!strcmp (argv[i], "-metric")) { 534863f95b1Smrg metric = 1; 535863f95b1Smrg continue; 536863f95b1Smrg } 537863f95b1Smrg if (!strcmp (argv[i], "-all")) { 538863f95b1Smrg tree = stats = bits = events = wm = size = shape = 1; 539863f95b1Smrg continue; 540863f95b1Smrg } 54196eca5d1Smrg if (!strcmp(argv[i], "-version")) { 54296eca5d1Smrg puts(PACKAGE_STRING); 54396eca5d1Smrg exit(0); 54496eca5d1Smrg } 54596eca5d1Smrg fprintf (stderr, "%s: unrecognized argument %s\n\n", 54696eca5d1Smrg program_name, argv[i]); 547863f95b1Smrg usage (); 548863f95b1Smrg } 549ff7e0accSmrg 550863f95b1Smrg Setup_Display_And_Screen (display_name, &dpy, &screen); 551863f95b1Smrg 552863f95b1Smrg /* preload atoms we may need later */ 553863f95b1Smrg Intern_Atom (dpy, "_NET_WM_NAME"); 554863f95b1Smrg Intern_Atom (dpy, "UTF8_STRING"); 555863f95b1Smrg if (wm) { 556863f95b1Smrg Intern_Atom (dpy, "_NET_WM_DESKTOP"); 557863f95b1Smrg Intern_Atom (dpy, "_NET_WM_WINDOW_TYPE"); 558863f95b1Smrg Intern_Atom (dpy, "_NET_WM_STATE"); 559863f95b1Smrg Intern_Atom (dpy, "_NET_WM_PID"); 560863f95b1Smrg Intern_Atom (dpy, "_NET_FRAME_EXTENTS"); 561863f95b1Smrg } 562863f95b1Smrg /* initialize scaling data */ 563863f95b1Smrg scale_init(screen); 564863f95b1Smrg 565863f95b1Smrg if (use_root) 566863f95b1Smrg window = screen->root; 567863f95b1Smrg else if (window_name) { 568863f95b1Smrg window = Window_With_Name (dpy, screen->root, window_name); 569863f95b1Smrg if (!window) 570863f95b1Smrg Fatal_Error ("No window with name \"%s\" exists!", window_name); 571863f95b1Smrg } 572ff7e0accSmrg 573863f95b1Smrg /* If no window selected on command line, let user pick one the hard way */ 574863f95b1Smrg if (!window) { 575863f95b1Smrg printf ("\n" 576863f95b1Smrg "xwininfo: Please select the window about which you\n" 577863f95b1Smrg " would like information by clicking the\n" 578863f95b1Smrg " mouse in that window.\n"); 579863f95b1Smrg Intern_Atom (dpy, "_NET_VIRTUAL_ROOTS"); 580863f95b1Smrg Intern_Atom (dpy, "WM_STATE"); 581863f95b1Smrg window = Select_Window (dpy, screen, !frame); 582863f95b1Smrg } 583ff7e0accSmrg 584863f95b1Smrg /* 585863f95b1Smrg * Do the actual displaying as per parameters 586863f95b1Smrg */ 587863f95b1Smrg if (!(children || tree || bits || events || wm || size)) 588863f95b1Smrg stats = 1; 589ff7e0accSmrg 590863f95b1Smrg /* 591863f95b1Smrg * make sure that the window is valid 592863f95b1Smrg */ 593863f95b1Smrg { 594863f95b1Smrg xcb_get_geometry_cookie_t gg_cookie = 595863f95b1Smrg xcb_get_geometry (dpy, window); 596ff7e0accSmrg 597863f95b1Smrg w->geometry = xcb_get_geometry_reply(dpy, gg_cookie, &err); 598ff7e0accSmrg 599863f95b1Smrg if (!w->geometry) { 600863f95b1Smrg if (err) 601863f95b1Smrg Print_X_Error (dpy, err); 602863f95b1Smrg 603cf2cd791Smrg Fatal_Error ("No such window with id %s.", window_id_str (window)); 604863f95b1Smrg } 605ff7e0accSmrg } 606863f95b1Smrg 607863f95b1Smrg /* Send requests to prefetch data we'll need */ 608863f95b1Smrg w->window = window; 609863f95b1Smrg w->net_wm_name_cookie = get_net_wm_name (dpy, window); 610853aa076Smrg w->wm_name_cookie = xcb_icccm_get_wm_name (dpy, window); 611863f95b1Smrg if (children || tree) 612863f95b1Smrg w->tree_cookie = xcb_query_tree (dpy, window); 613863f95b1Smrg if (stats) { 614863f95b1Smrg w->trans_coords_cookie = 615863f95b1Smrg xcb_translate_coordinates (dpy, window, w->geometry->root, 616863f95b1Smrg -(w->geometry->border_width), 617863f95b1Smrg -(w->geometry->border_width)); 618ff7e0accSmrg } 619863f95b1Smrg if (stats || bits || events) 620863f95b1Smrg w->attr_cookie = xcb_get_window_attributes (dpy, window); 621863f95b1Smrg if (stats || size) 622853aa076Smrg w->normal_hints_cookie = xcb_icccm_get_wm_normal_hints (dpy, window); 623863f95b1Smrg if (wm) { 624853aa076Smrg w->hints_cookie = xcb_icccm_get_wm_hints(dpy, window); 625863f95b1Smrg 626863f95b1Smrg atom_net_wm_desktop = Get_Atom (dpy, "_NET_WM_DESKTOP"); 627863f95b1Smrg if (atom_net_wm_desktop) { 628863f95b1Smrg w->wm_desktop_cookie = xcb_get_property 629863f95b1Smrg (dpy, False, window, atom_net_wm_desktop, 630863f95b1Smrg XCB_ATOM_CARDINAL, 0, 4); 631863f95b1Smrg } 632863f95b1Smrg 633863f95b1Smrg atom_net_wm_window_type = Get_Atom (dpy, "_NET_WM_WINDOW_TYPE"); 634863f95b1Smrg if (atom_net_wm_window_type) { 635863f95b1Smrg w->wm_window_type_cookie = xcb_get_property 636863f95b1Smrg (dpy, False, window, atom_net_wm_window_type, 637863f95b1Smrg XCB_ATOM_ATOM, 0, BUFSIZ); 638863f95b1Smrg } 639863f95b1Smrg 640863f95b1Smrg atom_net_wm_state = Get_Atom (dpy, "_NET_WM_STATE"); 641863f95b1Smrg if (atom_net_wm_state) { 642863f95b1Smrg w->wm_state_cookie = xcb_get_property 643863f95b1Smrg (dpy, False, window, atom_net_wm_state, 644863f95b1Smrg XCB_ATOM_ATOM, 0, BUFSIZ); 645863f95b1Smrg } 646863f95b1Smrg 647863f95b1Smrg atom_net_wm_pid = Get_Atom (dpy, "_NET_WM_PID"); 648863f95b1Smrg if (atom_net_wm_pid) { 649863f95b1Smrg w->wm_pid_cookie = xcb_get_property 650863f95b1Smrg (dpy, False, window, atom_net_wm_pid, 651863f95b1Smrg XCB_ATOM_CARDINAL, 0, BUFSIZ); 652863f95b1Smrg w->wm_client_machine_cookie = xcb_get_property 653863f95b1Smrg (dpy, False, window, XCB_ATOM_WM_CLIENT_MACHINE, 654863f95b1Smrg XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ); 655863f95b1Smrg } 656863f95b1Smrg 657863f95b1Smrg atom_net_frame_extents = Get_Atom (dpy, "_NET_FRAME_EXTENTS"); 658863f95b1Smrg if (atom_net_frame_extents) { 659863f95b1Smrg w->frame_extents_cookie = xcb_get_property 660863f95b1Smrg (dpy, False, window, atom_net_frame_extents, 661863f95b1Smrg XCB_ATOM_CARDINAL, 0, 4 * 4); 662863f95b1Smrg } 663ff7e0accSmrg } 664863f95b1Smrg if (size) 665853aa076Smrg w->zoom_cookie = xcb_icccm_get_wm_size_hints (dpy, window, 666853aa076Smrg XCB_ATOM_WM_ZOOM_HINTS); 667863f95b1Smrg xcb_flush (dpy); 668863f95b1Smrg 669863f95b1Smrg printf ("\nxwininfo: Window id: "); 670863f95b1Smrg Display_Window_Id (w, True); 671863f95b1Smrg if (children || tree) 672863f95b1Smrg Display_Tree_Info (w, tree); 673863f95b1Smrg if (stats) 674863f95b1Smrg Display_Stats_Info (w); 675863f95b1Smrg if (bits) 676863f95b1Smrg Display_Bits_Info (w); 677863f95b1Smrg if (events) 678863f95b1Smrg Display_Events_Info (w); 679863f95b1Smrg if (wm) 680863f95b1Smrg Display_WM_Info (w); 681863f95b1Smrg if (size) 682863f95b1Smrg Display_Size_Hints (w); 683863f95b1Smrg if (shape) 684863f95b1Smrg Display_Window_Shape (window); 685863f95b1Smrg printf ("\n"); 686863f95b1Smrg 687863f95b1Smrg wininfo_wipe (w); 688863f95b1Smrg xcb_disconnect (dpy); 689863f95b1Smrg#ifdef HAVE_ICONV 690863f95b1Smrg if (iconv_from_utf8 && (iconv_from_utf8 != (iconv_t) -1)) { 691863f95b1Smrg iconv_close (iconv_from_utf8); 692ff7e0accSmrg } 693863f95b1Smrg#endif 694863f95b1Smrg exit (0); 695863f95b1Smrg} 696863f95b1Smrg 697863f95b1Smrg/* Ensure win_attributes field is filled in */ 698863f95b1Smrgstatic xcb_get_window_attributes_reply_t * 699863f95b1Smrgfetch_win_attributes (struct wininfo *w) 700863f95b1Smrg{ 701863f95b1Smrg if (!w->win_attributes) { 702863f95b1Smrg w->win_attributes = 703863f95b1Smrg xcb_get_window_attributes_reply (dpy, w->attr_cookie, &err); 704863f95b1Smrg 705863f95b1Smrg if (!w->win_attributes) { 706863f95b1Smrg Print_X_Error (dpy, err); 707863f95b1Smrg Fatal_Error ("Can't get window attributes."); 708863f95b1Smrg } 709ff7e0accSmrg } 710863f95b1Smrg return w->win_attributes; 711863f95b1Smrg} 712863f95b1Smrg 713863f95b1Smrg#ifndef USE_XCB_ICCCM 714863f95b1Smrgstatic Bool 715cf2cd791Smrgwm_size_hints_reply (xcb_connection_t *wshr_dpy, xcb_get_property_cookie_t cookie, 716cf2cd791Smrg wm_size_hints_t *hints_return, xcb_generic_error_t **wshr_err) 717863f95b1Smrg{ 718cf2cd791Smrg xcb_get_property_reply_t *prop = xcb_get_property_reply (wshr_dpy, cookie, wshr_err); 719e8f4a63fSmrg size_t length; 720863f95b1Smrg 721863f95b1Smrg if (!prop || (prop->type != XCB_ATOM_WM_SIZE_HINTS) || 722863f95b1Smrg (prop->format != 32)) { 723863f95b1Smrg free (prop); 724863f95b1Smrg return False; 725ff7e0accSmrg } 726863f95b1Smrg 727863f95b1Smrg memset (hints_return, 0, sizeof(wm_size_hints_t)); 728863f95b1Smrg 729e8f4a63fSmrg length = (size_t) xcb_get_property_value_length(prop); 730863f95b1Smrg if (length > sizeof(wm_size_hints_t)) 731863f95b1Smrg length = sizeof(wm_size_hints_t); 732863f95b1Smrg memcpy (hints_return, xcb_get_property_value (prop), length); 733863f95b1Smrg 734863f95b1Smrg free (prop); 735863f95b1Smrg return True; 736863f95b1Smrg} 737863f95b1Smrg 738853aa076Smrg#define xcb_icccm_get_wm_normal_hints_reply wm_size_hints_reply 739853aa076Smrg#define xcb_icccm_get_wm_size_hints_reply wm_size_hints_reply 740863f95b1Smrg#endif 741863f95b1Smrg 742863f95b1Smrg 743863f95b1Smrg 744863f95b1Smrg/* Ensure normal_hints field is filled in */ 745863f95b1Smrgstatic xcb_size_hints_t * 746863f95b1Smrgfetch_normal_hints (struct wininfo *w, xcb_size_hints_t *hints_return) 747863f95b1Smrg{ 748863f95b1Smrg xcb_size_hints_t hints; 749863f95b1Smrg 750863f95b1Smrg if (!w->normal_hints) { 751853aa076Smrg if (xcb_icccm_get_wm_normal_hints_reply (dpy, w->normal_hints_cookie, 752853aa076Smrg &hints, NULL)) { 753863f95b1Smrg w->normal_hints = malloc (sizeof(xcb_size_hints_t)); 754863f95b1Smrg if (w->normal_hints) 755863f95b1Smrg memcpy(w->normal_hints, &hints, sizeof(xcb_size_hints_t)); 756863f95b1Smrg } 757ff7e0accSmrg } 758863f95b1Smrg if (hints_return && w->normal_hints) 759863f95b1Smrg memcpy(hints_return, w->normal_hints, sizeof(xcb_size_hints_t)); 760863f95b1Smrg return w->normal_hints; 761ff7e0accSmrg} 762ff7e0accSmrg 763ff7e0accSmrg 764ff7e0accSmrg/* 765ff7e0accSmrg * Lookup: lookup a code in a table. 766ff7e0accSmrg */ 767ff7e0accSmrgstatic char _lookup_buffer[100]; 768ff7e0accSmrg 769ff7e0accSmrgstatic const char * 770863f95b1SmrgLookupL (long code, const binding *table) 771ff7e0accSmrg{ 772863f95b1Smrg const char *name = NULL; 773ff7e0accSmrg 774863f95b1Smrg while (table->name) { 775863f95b1Smrg if (table->code == code) { 776863f95b1Smrg name = table->name; 777863f95b1Smrg break; 778ff7e0accSmrg } 779863f95b1Smrg table++; 780863f95b1Smrg } 781ff7e0accSmrg 782863f95b1Smrg if (name == NULL) { 783863f95b1Smrg snprintf (_lookup_buffer, sizeof(_lookup_buffer), 784863f95b1Smrg "unknown (code = %ld. = 0x%lx)", code, code); 785863f95b1Smrg name = _lookup_buffer; 786863f95b1Smrg } 787863f95b1Smrg 788863f95b1Smrg return (name); 789ff7e0accSmrg} 790ff7e0accSmrg 791ff7e0accSmrgstatic const char * 792863f95b1SmrgLookup (int code, const binding *table) 793ff7e0accSmrg{ 794863f95b1Smrg return LookupL ((long)code, table); 795ff7e0accSmrg} 796ff7e0accSmrg 797ff7e0accSmrg/* 798ff7e0accSmrg * Routine to display a window id in dec/hex with name if window has one 799863f95b1Smrg * 800863f95b1Smrg * Requires wininfo members initialized: window, wm_name_cookie 801ff7e0accSmrg */ 802ff7e0accSmrg 803ff7e0accSmrgstatic void 804863f95b1SmrgDisplay_Window_Id (struct wininfo *w, Bool newline_wanted) 805ff7e0accSmrg{ 806863f95b1Smrg#ifdef USE_XCB_ICCCM 807853aa076Smrg xcb_icccm_get_text_property_reply_t wmn_reply; 808853aa076Smrg uint8_t got_reply = False; 809ff7e0accSmrg#endif 810863f95b1Smrg xcb_get_property_reply_t *prop; 811863f95b1Smrg const char *wm_name = NULL; 812863f95b1Smrg unsigned int wm_name_len = 0; 813863f95b1Smrg xcb_atom_t wm_name_encoding = XCB_NONE; 814ff7e0accSmrg 815cf2cd791Smrg printf ("%s", window_id_str (w->window)); 816863f95b1Smrg 817863f95b1Smrg if (!w->window) { 818863f95b1Smrg printf (" (none)"); 819ff7e0accSmrg } else { 820863f95b1Smrg if (w->window == screen->root) { 821863f95b1Smrg printf (" (the root window)"); 822ff7e0accSmrg } 823863f95b1Smrg /* Get window name if any */ 824863f95b1Smrg prop = xcb_get_property_reply (dpy, w->net_wm_name_cookie, NULL); 825863f95b1Smrg if (prop && (prop->type != XCB_NONE)) { 826863f95b1Smrg wm_name = xcb_get_property_value (prop); 827863f95b1Smrg wm_name_len = xcb_get_property_value_length (prop); 828863f95b1Smrg wm_name_encoding = prop->type; 829853aa076Smrg } else { /* No _NET_WM_NAME, check WM_NAME */ 830863f95b1Smrg#ifdef USE_XCB_ICCCM 831853aa076Smrg got_reply = xcb_icccm_get_wm_name_reply (dpy, w->wm_name_cookie, 832853aa076Smrg &wmn_reply, NULL); 833863f95b1Smrg if (got_reply) { 834863f95b1Smrg wm_name = wmn_reply.name; 835863f95b1Smrg wm_name_len = wmn_reply.name_len; 836863f95b1Smrg wm_name_encoding = wmn_reply.encoding; 837863f95b1Smrg } 838ff7e0accSmrg#else 839863f95b1Smrg prop = xcb_get_property_reply (dpy, w->wm_name_cookie, NULL); 840863f95b1Smrg if (prop && (prop->type != XCB_NONE)) { 841863f95b1Smrg wm_name = xcb_get_property_value (prop); 842863f95b1Smrg wm_name_len = xcb_get_property_value_length (prop); 843863f95b1Smrg wm_name_encoding = prop->type; 844863f95b1Smrg } 845863f95b1Smrg#endif 846ff7e0accSmrg } 847853aa076Smrg if (wm_name_len == 0) { 848863f95b1Smrg printf (" (has no name)"); 849863f95b1Smrg } else { 850863f95b1Smrg if (wm_name_encoding == XCB_ATOM_STRING) { 851863f95b1Smrg printf (" \"%.*s\"", wm_name_len, wm_name); 852863f95b1Smrg } else if (wm_name_encoding == atom_utf8_string) { 853cf2cd791Smrg print_utf8 (" \"", wm_name, wm_name_len, "\""); 854863f95b1Smrg } else { 855863f95b1Smrg /* Encodings we don't support, including COMPOUND_TEXT */ 856863f95b1Smrg const char *enc_name = Get_Atom_Name (dpy, wm_name_encoding); 857863f95b1Smrg if (enc_name) { 858863f95b1Smrg printf (" (name in unsupported encoding %s)", enc_name); 859863f95b1Smrg } else { 860863f95b1Smrg printf (" (name in unsupported encoding ATOM 0x%x)", 861863f95b1Smrg wm_name_encoding); 862863f95b1Smrg } 863863f95b1Smrg } 864863f95b1Smrg } 865863f95b1Smrg#ifdef USE_XCB_ICCCM 866863f95b1Smrg if (got_reply) 867853aa076Smrg xcb_icccm_get_text_property_reply_wipe (&wmn_reply); 868863f95b1Smrg#else 869863f95b1Smrg free (prop); 870ff7e0accSmrg#endif 871ff7e0accSmrg } 872ff7e0accSmrg 873ff7e0accSmrg if (newline_wanted) 874863f95b1Smrg printf ("\n"); 875ff7e0accSmrg 876ff7e0accSmrg return; 877ff7e0accSmrg} 878ff7e0accSmrg 879ff7e0accSmrg 880ff7e0accSmrg/* 881ff7e0accSmrg * Display Stats on window 882ff7e0accSmrg */ 883ff7e0accSmrgstatic const binding _window_classes[] = { 884863f95b1Smrg { XCB_WINDOW_CLASS_INPUT_OUTPUT, "InputOutput" }, 885863f95b1Smrg { XCB_WINDOW_CLASS_INPUT_ONLY, "InputOnly" }, 88610998002Smrg { 0, NULL } }; 887ff7e0accSmrg 888ff7e0accSmrgstatic const binding _map_states[] = { 889863f95b1Smrg { XCB_MAP_STATE_UNMAPPED, "IsUnMapped" }, 890863f95b1Smrg { XCB_MAP_STATE_UNVIEWABLE, "IsUnviewable" }, 891863f95b1Smrg { XCB_MAP_STATE_VIEWABLE, "IsViewable" }, 89210998002Smrg { 0, NULL } }; 893ff7e0accSmrg 894ff7e0accSmrgstatic const binding _backing_store_states[] = { 895863f95b1Smrg { XCB_BACKING_STORE_NOT_USEFUL, "NotUseful" }, 896863f95b1Smrg { XCB_BACKING_STORE_WHEN_MAPPED,"WhenMapped" }, 897863f95b1Smrg { XCB_BACKING_STORE_ALWAYS, "Always" }, 89810998002Smrg { 0, NULL } }; 899ff7e0accSmrg 900ff7e0accSmrgstatic const binding _bit_gravity_states[] = { 901863f95b1Smrg { XCB_GRAVITY_BIT_FORGET, "ForgetGravity" }, 902863f95b1Smrg { XCB_GRAVITY_NORTH_WEST, "NorthWestGravity" }, 903863f95b1Smrg { XCB_GRAVITY_NORTH, "NorthGravity" }, 904863f95b1Smrg { XCB_GRAVITY_NORTH_EAST, "NorthEastGravity" }, 905863f95b1Smrg { XCB_GRAVITY_WEST, "WestGravity" }, 906863f95b1Smrg { XCB_GRAVITY_CENTER, "CenterGravity" }, 907863f95b1Smrg { XCB_GRAVITY_EAST, "EastGravity" }, 908863f95b1Smrg { XCB_GRAVITY_SOUTH_WEST, "SouthWestGravity" }, 909863f95b1Smrg { XCB_GRAVITY_SOUTH, "SouthGravity" }, 910863f95b1Smrg { XCB_GRAVITY_SOUTH_EAST, "SouthEastGravity" }, 911863f95b1Smrg { XCB_GRAVITY_STATIC, "StaticGravity" }, 91210998002Smrg { 0, NULL }}; 913ff7e0accSmrg 914ff7e0accSmrgstatic const binding _window_gravity_states[] = { 915863f95b1Smrg { XCB_GRAVITY_WIN_UNMAP, "UnmapGravity" }, 916863f95b1Smrg { XCB_GRAVITY_NORTH_WEST, "NorthWestGravity" }, 917863f95b1Smrg { XCB_GRAVITY_NORTH, "NorthGravity" }, 918863f95b1Smrg { XCB_GRAVITY_NORTH_EAST, "NorthEastGravity" }, 919863f95b1Smrg { XCB_GRAVITY_WEST, "WestGravity" }, 920863f95b1Smrg { XCB_GRAVITY_CENTER, "CenterGravity" }, 921863f95b1Smrg { XCB_GRAVITY_EAST, "EastGravity" }, 922863f95b1Smrg { XCB_GRAVITY_SOUTH_WEST, "SouthWestGravity" }, 923863f95b1Smrg { XCB_GRAVITY_SOUTH, "SouthGravity" }, 924863f95b1Smrg { XCB_GRAVITY_SOUTH_EAST, "SouthEastGravity" }, 925863f95b1Smrg { XCB_GRAVITY_STATIC, "StaticGravity" }, 92610998002Smrg { 0, NULL }}; 927ff7e0accSmrg 928ff7e0accSmrgstatic const binding _visual_classes[] = { 929863f95b1Smrg { XCB_VISUAL_CLASS_STATIC_GRAY, "StaticGray" }, 930863f95b1Smrg { XCB_VISUAL_CLASS_GRAY_SCALE, "GrayScale" }, 931863f95b1Smrg { XCB_VISUAL_CLASS_STATIC_COLOR,"StaticColor" }, 932863f95b1Smrg { XCB_VISUAL_CLASS_PSEUDO_COLOR,"PseudoColor" }, 933863f95b1Smrg { XCB_VISUAL_CLASS_TRUE_COLOR, "TrueColor" }, 934863f95b1Smrg { XCB_VISUAL_CLASS_DIRECT_COLOR,"DirectColor" }, 93510998002Smrg { 0, NULL }}; 936ff7e0accSmrg 937863f95b1Smrg/* 938863f95b1Smrg * Requires wininfo members initialized: 939863f95b1Smrg * window, geometry, attr_cookie, trans_coords_cookie, normal_hints_cookie 940863f95b1Smrg */ 941ff7e0accSmrgstatic void 942863f95b1SmrgDisplay_Stats_Info (struct wininfo *w) 943ff7e0accSmrg{ 944863f95b1Smrg xcb_translate_coordinates_reply_t *trans_coords; 945863f95b1Smrg xcb_get_window_attributes_reply_t *win_attributes; 946863f95b1Smrg xcb_size_hints_t hints; 947863f95b1Smrg 948863f95b1Smrg int dw = screen->width_in_pixels, dh = screen->height_in_pixels; 949863f95b1Smrg int rx, ry, xright, ybelow; 950863f95b1Smrg int showright = 0, showbelow = 0; 951863f95b1Smrg xcb_window_t wmframe, parent; 952863f95b1Smrg 953863f95b1Smrg trans_coords = 954863f95b1Smrg xcb_translate_coordinates_reply (dpy, w->trans_coords_cookie, NULL); 955863f95b1Smrg if (!trans_coords) 956863f95b1Smrg Fatal_Error ("Can't get translated coordinates."); 957863f95b1Smrg 958863f95b1Smrg rx = (int16_t)trans_coords->dst_x; 959863f95b1Smrg ry = (int16_t)trans_coords->dst_y; 960863f95b1Smrg free (trans_coords); 961863f95b1Smrg 962863f95b1Smrg xright = (dw - rx - w->geometry->border_width * 2 - 963863f95b1Smrg w->geometry->width); 964863f95b1Smrg ybelow = (dh - ry - w->geometry->border_width * 2 - 965863f95b1Smrg w->geometry->height); 966863f95b1Smrg 967863f95b1Smrg 968863f95b1Smrg printf ("\n"); 969863f95b1Smrg printf (" Absolute upper-left X: %s\n", xscale (rx)); 970863f95b1Smrg printf (" Absolute upper-left Y: %s\n", yscale (ry)); 971863f95b1Smrg printf (" Relative upper-left X: %s\n", xscale (w->geometry->x)); 972863f95b1Smrg printf (" Relative upper-left Y: %s\n", yscale (w->geometry->y)); 973863f95b1Smrg printf (" Width: %s\n", xscale (w->geometry->width)); 974863f95b1Smrg printf (" Height: %s\n", yscale (w->geometry->height)); 975863f95b1Smrg printf (" Depth: %d\n", w->geometry->depth); 976863f95b1Smrg 977863f95b1Smrg win_attributes = fetch_win_attributes (w); 978863f95b1Smrg 979863f95b1Smrg printf (" Visual: 0x%lx\n", (unsigned long) win_attributes->visual); 980863f95b1Smrg if (screen) 981863f95b1Smrg { 982863f95b1Smrg xcb_depth_iterator_t depth_iter; 983863f95b1Smrg xcb_visualtype_t *visual_type = NULL; 984863f95b1Smrg 985863f95b1Smrg depth_iter = xcb_screen_allowed_depths_iterator (screen); 986863f95b1Smrg for (; depth_iter.rem; xcb_depth_next (&depth_iter)) { 987863f95b1Smrg xcb_visualtype_iterator_t visual_iter; 988863f95b1Smrg 989863f95b1Smrg visual_iter = xcb_depth_visuals_iterator (depth_iter.data); 990863f95b1Smrg for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) { 991cf2cd791Smrg if (win_attributes->visual == visual_iter.data->visual_id) { 992863f95b1Smrg visual_type = visual_iter.data; 993863f95b1Smrg break; 994863f95b1Smrg } 995863f95b1Smrg } 996863f95b1Smrg } 997863f95b1Smrg if (visual_type) 998863f95b1Smrg printf (" Visual Class: %s\n", Lookup (visual_type->_class, 999863f95b1Smrg _visual_classes)); 1000863f95b1Smrg } 1001863f95b1Smrg 1002863f95b1Smrg printf (" Border width: %s\n", bscale (w->geometry->border_width)); 1003863f95b1Smrg printf (" Class: %s\n", 1004863f95b1Smrg Lookup (win_attributes->_class, _window_classes)); 1005863f95b1Smrg printf (" Colormap: 0x%lx (%sinstalled)\n", 1006863f95b1Smrg (unsigned long) win_attributes->colormap, 1007863f95b1Smrg win_attributes->map_is_installed ? "" : "not "); 1008863f95b1Smrg printf (" Bit Gravity State: %s\n", 1009863f95b1Smrg Lookup (win_attributes->bit_gravity, _bit_gravity_states)); 1010863f95b1Smrg printf (" Window Gravity State: %s\n", 1011863f95b1Smrg Lookup (win_attributes->win_gravity, _window_gravity_states)); 1012863f95b1Smrg printf (" Backing Store State: %s\n", 1013863f95b1Smrg Lookup (win_attributes->backing_store, _backing_store_states)); 1014863f95b1Smrg printf (" Save Under State: %s\n", 1015863f95b1Smrg win_attributes->save_under ? "yes" : "no"); 1016863f95b1Smrg printf (" Map State: %s\n", 1017863f95b1Smrg Lookup (win_attributes->map_state, _map_states)); 1018863f95b1Smrg printf (" Override Redirect State: %s\n", 1019863f95b1Smrg win_attributes->override_redirect ? "yes" : "no"); 1020863f95b1Smrg printf (" Corners: +%d+%d -%d+%d -%d-%d +%d-%d\n", 1021863f95b1Smrg rx, ry, xright, ry, xright, ybelow, rx, ybelow); 1022863f95b1Smrg 1023863f95b1Smrg /* 1024863f95b1Smrg * compute geometry string that would recreate window 1025863f95b1Smrg */ 1026863f95b1Smrg printf (" -geometry "); 1027863f95b1Smrg 1028863f95b1Smrg /* compute size in appropriate units */ 1029863f95b1Smrg if (!fetch_normal_hints (w, &hints)) 1030863f95b1Smrg hints.flags = 0; 1031863f95b1Smrg 1032853aa076Smrg if ((hints.flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC) && 1033863f95b1Smrg (hints.width_inc != 0) && (hints.height_inc != 0)) { 1034853aa076Smrg if (hints.flags & 1035853aa076Smrg (XCB_ICCCM_SIZE_HINT_BASE_SIZE|XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)) { 1036853aa076Smrg if (hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) { 1037863f95b1Smrg w->geometry->width -= hints.base_width; 1038863f95b1Smrg w->geometry->height -= hints.base_height; 1039863f95b1Smrg } else { 1040863f95b1Smrg /* ICCCM says MinSize is default for BaseSize */ 1041863f95b1Smrg w->geometry->width -= hints.min_width; 1042863f95b1Smrg w->geometry->height -= hints.min_height; 1043863f95b1Smrg } 1044863f95b1Smrg } 1045863f95b1Smrg printf ("%dx%d", w->geometry->width/hints.width_inc, 1046863f95b1Smrg w->geometry->height/hints.height_inc); 1047863f95b1Smrg } else 1048863f95b1Smrg printf ("%dx%d", w->geometry->width, w->geometry->height); 1049863f95b1Smrg 1050853aa076Smrg if (!(hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)) 1051863f95b1Smrg hints.win_gravity = XCB_GRAVITY_NORTH_WEST; /* per ICCCM */ 1052863f95b1Smrg /* find our window manager frame, if any */ 1053863f95b1Smrg for (wmframe = parent = w->window; parent != 0 ; wmframe = parent) { 1054863f95b1Smrg xcb_query_tree_cookie_t qt_cookie; 1055863f95b1Smrg xcb_query_tree_reply_t *tree; 1056863f95b1Smrg 1057863f95b1Smrg qt_cookie = xcb_query_tree (dpy, wmframe); 1058863f95b1Smrg tree = xcb_query_tree_reply (dpy, qt_cookie, &err); 1059863f95b1Smrg if (!tree) { 1060863f95b1Smrg Print_X_Error (dpy, err); 1061863f95b1Smrg Fatal_Error ("Can't query window tree."); 1062863f95b1Smrg } 1063863f95b1Smrg parent = tree->parent; 1064863f95b1Smrg free (tree); 1065863f95b1Smrg if (parent == w->geometry->root || !parent) 1066863f95b1Smrg break; 1067863f95b1Smrg } 1068863f95b1Smrg if (wmframe != w->window) { 1069863f95b1Smrg /* WM reparented, so find edges of the frame */ 1070863f95b1Smrg /* Only works for ICCCM-compliant WMs, and then only if the 1071863f95b1Smrg window has corner gravity. We would need to know the original width 1072863f95b1Smrg of the window to correctly handle the other gravities. */ 1073863f95b1Smrg xcb_get_geometry_cookie_t geom_cookie; 1074863f95b1Smrg xcb_get_geometry_reply_t *frame_geometry; 1075863f95b1Smrg 1076863f95b1Smrg geom_cookie = xcb_get_geometry (dpy, wmframe); 1077863f95b1Smrg frame_geometry = xcb_get_geometry_reply (dpy, geom_cookie, &err); 1078863f95b1Smrg 1079863f95b1Smrg if (!frame_geometry) { 1080863f95b1Smrg Print_X_Error (dpy, err); 1081863f95b1Smrg Fatal_Error ("Can't get frame geometry."); 1082863f95b1Smrg } 1083863f95b1Smrg switch (hints.win_gravity) { 1084863f95b1Smrg case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST: 1085863f95b1Smrg case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST: 1086863f95b1Smrg case XCB_GRAVITY_WEST: 1087863f95b1Smrg rx = frame_geometry->x; 1088863f95b1Smrg } 1089863f95b1Smrg switch (hints.win_gravity) { 1090863f95b1Smrg case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST: 1091863f95b1Smrg case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST: 1092863f95b1Smrg case XCB_GRAVITY_EAST: 1093863f95b1Smrg xright = dw - frame_geometry->x - frame_geometry->width - 1094863f95b1Smrg (2 * frame_geometry->border_width); 1095863f95b1Smrg } 1096863f95b1Smrg switch (hints.win_gravity) { 1097863f95b1Smrg case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST: 1098863f95b1Smrg case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST: 1099863f95b1Smrg case XCB_GRAVITY_NORTH: 1100863f95b1Smrg ry = frame_geometry->y; 1101863f95b1Smrg } 1102863f95b1Smrg switch (hints.win_gravity) { 1103863f95b1Smrg case XCB_GRAVITY_NORTH_WEST: case XCB_GRAVITY_SOUTH_WEST: 1104863f95b1Smrg case XCB_GRAVITY_NORTH_EAST: case XCB_GRAVITY_SOUTH_EAST: 1105863f95b1Smrg case XCB_GRAVITY_SOUTH: 1106863f95b1Smrg ybelow = dh - frame_geometry->y - frame_geometry->height - 1107863f95b1Smrg (2 * frame_geometry->border_width); 1108863f95b1Smrg } 1109863f95b1Smrg free (frame_geometry); 1110863f95b1Smrg } 1111863f95b1Smrg /* If edge gravity, offer a corner on that edge (because the application 1112863f95b1Smrg programmer cares about that edge), otherwise offer upper left unless 1113863f95b1Smrg some other corner is close to an edge of the screen. 1114863f95b1Smrg (For corner gravity, assume gravity was set by XWMGeometry. 1115863f95b1Smrg For CenterGravity, it doesn't matter.) */ 1116863f95b1Smrg if (hints.win_gravity == XCB_GRAVITY_EAST || 1117863f95b1Smrg (abs (xright) <= 100 && abs (xright) < abs (rx) 1118863f95b1Smrg && hints.win_gravity != XCB_GRAVITY_WEST)) 1119863f95b1Smrg showright = 1; 1120863f95b1Smrg if (hints.win_gravity == XCB_GRAVITY_SOUTH || 1121863f95b1Smrg (abs (ybelow) <= 100 && abs (ybelow) < abs (ry) 1122863f95b1Smrg && hints.win_gravity != XCB_GRAVITY_NORTH)) 1123863f95b1Smrg showbelow = 1; 1124863f95b1Smrg 1125863f95b1Smrg if (showright) 1126863f95b1Smrg printf ("-%d", xright); 1127863f95b1Smrg else 1128863f95b1Smrg printf ("+%d", rx); 1129863f95b1Smrg if (showbelow) 1130863f95b1Smrg printf ("-%d", ybelow); 1131863f95b1Smrg else 1132863f95b1Smrg printf ("+%d", ry); 1133863f95b1Smrg printf ("\n"); 1134ff7e0accSmrg} 1135ff7e0accSmrg 1136ff7e0accSmrg 1137ff7e0accSmrg/* 1138ff7e0accSmrg * Display bits info: 1139ff7e0accSmrg */ 1140ff7e0accSmrgstatic const binding _gravities[] = { 1141863f95b1Smrg /* WARNING: the first two of these have the same value - see code */ 1142863f95b1Smrg { XCB_GRAVITY_WIN_UNMAP, "UnMapGravity" }, 1143863f95b1Smrg { XCB_GRAVITY_BIT_FORGET, "ForgetGravity" }, 1144863f95b1Smrg { XCB_GRAVITY_NORTH_WEST, "NorthWestGravity" }, 1145863f95b1Smrg { XCB_GRAVITY_NORTH, "NorthGravity" }, 1146863f95b1Smrg { XCB_GRAVITY_NORTH_EAST, "NorthEastGravity" }, 1147863f95b1Smrg { XCB_GRAVITY_WEST, "WestGravity" }, 1148863f95b1Smrg { XCB_GRAVITY_CENTER, "CenterGravity" }, 1149863f95b1Smrg { XCB_GRAVITY_EAST, "EastGravity" }, 1150863f95b1Smrg { XCB_GRAVITY_SOUTH_WEST, "SouthWestGravity" }, 1151863f95b1Smrg { XCB_GRAVITY_SOUTH, "SouthGravity" }, 1152863f95b1Smrg { XCB_GRAVITY_SOUTH_EAST, "SouthEastGravity" }, 1153863f95b1Smrg { XCB_GRAVITY_STATIC, "StaticGravity" }, 115410998002Smrg { 0, NULL } }; 1155ff7e0accSmrg 1156ff7e0accSmrgstatic const binding _backing_store_hint[] = { 1157863f95b1Smrg { XCB_BACKING_STORE_NOT_USEFUL, "NotUseful" }, 1158863f95b1Smrg { XCB_BACKING_STORE_WHEN_MAPPED,"WhenMapped" }, 1159863f95b1Smrg { XCB_BACKING_STORE_ALWAYS, "Always" }, 116010998002Smrg { 0, NULL } }; 1161ff7e0accSmrg 1162ff7e0accSmrgstatic const binding _bool[] = { 1163ff7e0accSmrg { 0, "No" }, 1164ff7e0accSmrg { 1, "Yes" }, 116510998002Smrg { 0, NULL } }; 1166ff7e0accSmrg 1167863f95b1Smrg/* 1168863f95b1Smrg * Requires wininfo members initialized: 1169863f95b1Smrg * window, attr_cookie (or win_attributes) 1170863f95b1Smrg */ 1171ff7e0accSmrgstatic void 1172863f95b1SmrgDisplay_Bits_Info (struct wininfo * w) 1173ff7e0accSmrg{ 1174863f95b1Smrg xcb_get_window_attributes_reply_t *win_attributes 1175863f95b1Smrg = fetch_win_attributes (w); 1176863f95b1Smrg 1177863f95b1Smrg printf ("\n"); 1178863f95b1Smrg printf (" Bit gravity: %s\n", 1179863f95b1Smrg Lookup (win_attributes->bit_gravity, _gravities+1)); 1180863f95b1Smrg printf (" Window gravity: %s\n", 1181863f95b1Smrg Lookup (win_attributes->win_gravity, _gravities)); 1182863f95b1Smrg printf (" Backing-store hint: %s\n", 1183863f95b1Smrg Lookup (win_attributes->backing_store, _backing_store_hint)); 1184863f95b1Smrg printf (" Backing-planes to be preserved: 0x%lx\n", 1185863f95b1Smrg (unsigned long) win_attributes->backing_planes); 1186863f95b1Smrg printf (" Backing pixel: %ld\n", 1187863f95b1Smrg (unsigned long) win_attributes->backing_pixel); 1188863f95b1Smrg printf (" Save-unders: %s\n", 1189863f95b1Smrg Lookup (win_attributes->save_under, _bool)); 1190ff7e0accSmrg} 1191ff7e0accSmrg 1192ff7e0accSmrg 1193ff7e0accSmrg/* 1194ff7e0accSmrg * Routine to display all events in an event mask 1195ff7e0accSmrg */ 1196ff7e0accSmrgstatic const binding _event_mask_names[] = { 1197863f95b1Smrg { XCB_EVENT_MASK_KEY_PRESS, "KeyPress" }, 1198863f95b1Smrg { XCB_EVENT_MASK_KEY_RELEASE, "KeyRelease" }, 1199863f95b1Smrg { XCB_EVENT_MASK_BUTTON_PRESS, "ButtonPress" }, 1200863f95b1Smrg { XCB_EVENT_MASK_BUTTON_RELEASE, "ButtonRelease" }, 1201863f95b1Smrg { XCB_EVENT_MASK_ENTER_WINDOW, "EnterWindow" }, 1202863f95b1Smrg { XCB_EVENT_MASK_LEAVE_WINDOW, "LeaveWindow" }, 1203863f95b1Smrg { XCB_EVENT_MASK_POINTER_MOTION, "PointerMotion" }, 1204863f95b1Smrg { XCB_EVENT_MASK_POINTER_MOTION_HINT, "PointerMotionHint" }, 1205863f95b1Smrg { XCB_EVENT_MASK_BUTTON_1_MOTION, "Button1Motion" }, 1206863f95b1Smrg { XCB_EVENT_MASK_BUTTON_2_MOTION, "Button2Motion" }, 1207863f95b1Smrg { XCB_EVENT_MASK_BUTTON_3_MOTION, "Button3Motion" }, 1208863f95b1Smrg { XCB_EVENT_MASK_BUTTON_4_MOTION, "Button4Motion" }, 1209863f95b1Smrg { XCB_EVENT_MASK_BUTTON_5_MOTION, "Button5Motion" }, 1210863f95b1Smrg { XCB_EVENT_MASK_BUTTON_MOTION, "ButtonMotion" }, 1211863f95b1Smrg { XCB_EVENT_MASK_KEYMAP_STATE, "KeymapState" }, 1212863f95b1Smrg { XCB_EVENT_MASK_EXPOSURE, "Exposure" }, 1213863f95b1Smrg { XCB_EVENT_MASK_VISIBILITY_CHANGE, "VisibilityChange" }, 1214863f95b1Smrg { XCB_EVENT_MASK_STRUCTURE_NOTIFY, "StructureNotify" }, 1215863f95b1Smrg { XCB_EVENT_MASK_RESIZE_REDIRECT, "ResizeRedirect" }, 1216863f95b1Smrg { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, "SubstructureNotify" }, 1217863f95b1Smrg { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, "SubstructureRedirect" }, 1218863f95b1Smrg { XCB_EVENT_MASK_FOCUS_CHANGE, "FocusChange" }, 1219863f95b1Smrg { XCB_EVENT_MASK_PROPERTY_CHANGE, "PropertyChange" }, 1220863f95b1Smrg { XCB_EVENT_MASK_COLOR_MAP_CHANGE, "ColormapChange" }, 1221863f95b1Smrg { XCB_EVENT_MASK_OWNER_GRAB_BUTTON, "OwnerGrabButton" }, 122210998002Smrg { 0, NULL } }; 1223ff7e0accSmrg 1224ff7e0accSmrgstatic void 1225863f95b1SmrgDisplay_Event_Mask (long mask) 1226ff7e0accSmrg{ 1227e8f4a63fSmrg unsigned long bit, bit_mask; 1228ff7e0accSmrg 1229863f95b1Smrg for (bit=0, bit_mask=1; bit < sizeof(long)*8; bit++, bit_mask <<= 1) 1230863f95b1Smrg if (mask & bit_mask) 1231863f95b1Smrg printf (" %s\n", 1232863f95b1Smrg LookupL (bit_mask, _event_mask_names)); 1233ff7e0accSmrg} 1234ff7e0accSmrg 1235ff7e0accSmrg 1236ff7e0accSmrg/* 1237ff7e0accSmrg * Display info on events 1238863f95b1Smrg * 1239863f95b1Smrg * Requires wininfo members initialized: 1240863f95b1Smrg * window, attr_cookie (or win_attributes) 1241ff7e0accSmrg */ 1242ff7e0accSmrgstatic void 1243863f95b1SmrgDisplay_Events_Info (struct wininfo *w) 1244ff7e0accSmrg{ 1245863f95b1Smrg xcb_get_window_attributes_reply_t *win_attributes 1246863f95b1Smrg = fetch_win_attributes (w); 1247ff7e0accSmrg 1248863f95b1Smrg printf ("\n"); 1249863f95b1Smrg printf (" Someone wants these events:\n"); 1250863f95b1Smrg Display_Event_Mask (win_attributes->all_event_masks); 1251ff7e0accSmrg 1252863f95b1Smrg printf (" Do not propagate these events:\n"); 1253863f95b1Smrg Display_Event_Mask (win_attributes->do_not_propagate_mask); 1254ff7e0accSmrg 1255863f95b1Smrg printf (" Override redirection?: %s\n", 1256863f95b1Smrg Lookup (win_attributes->override_redirect, _bool)); 1257ff7e0accSmrg} 1258ff7e0accSmrg 1259ff7e0accSmrg 1260ff7e0accSmrg /* left out visual stuff */ 1261ff7e0accSmrg /* left out colormap */ 1262ff7e0accSmrg /* left out map_installed */ 1263ff7e0accSmrg 1264ff7e0accSmrg 1265ff7e0accSmrg/* 1266ff7e0accSmrg * Display root, parent, and (recursively) children information 1267ff7e0accSmrg * recurse - true to show children information 1268863f95b1Smrg * 1269863f95b1Smrg * Requires wininfo members initialized: window, tree_cookie 1270ff7e0accSmrg */ 1271ff7e0accSmrgstatic void 1272863f95b1SmrgDisplay_Tree_Info (struct wininfo *w, int recurse) 1273ff7e0accSmrg{ 1274863f95b1Smrg display_tree_info_1 (w, recurse, 0); 1275ff7e0accSmrg} 1276ff7e0accSmrg 1277ff7e0accSmrg/* 1278ff7e0accSmrg * level - recursion level 1279ff7e0accSmrg */ 1280ff7e0accSmrgstatic void 1281863f95b1Smrgdisplay_tree_info_1 (struct wininfo *w, int recurse, int level) 1282ff7e0accSmrg{ 1283863f95b1Smrg int i, j; 1284863f95b1Smrg unsigned int num_children; 1285863f95b1Smrg xcb_query_tree_reply_t *tree; 1286863f95b1Smrg 1287863f95b1Smrg tree = xcb_query_tree_reply (dpy, w->tree_cookie, &err); 1288863f95b1Smrg if (!tree) { 1289863f95b1Smrg Print_X_Error (dpy, err); 1290863f95b1Smrg Fatal_Error ("Can't query window tree."); 1291863f95b1Smrg } 1292ff7e0accSmrg 1293863f95b1Smrg if (level == 0) { 1294863f95b1Smrg struct wininfo rw, pw; 1295863f95b1Smrg rw.window = tree->root; 1296863f95b1Smrg rw.net_wm_name_cookie = get_net_wm_name (dpy, rw.window); 1297853aa076Smrg rw.wm_name_cookie = xcb_icccm_get_wm_name (dpy, rw.window); 1298863f95b1Smrg pw.window = tree->parent; 1299863f95b1Smrg pw.net_wm_name_cookie = get_net_wm_name (dpy, pw.window); 1300853aa076Smrg pw.wm_name_cookie = xcb_icccm_get_wm_name (dpy, pw.window); 1301863f95b1Smrg xcb_flush (dpy); 1302863f95b1Smrg 1303863f95b1Smrg printf ("\n"); 1304863f95b1Smrg printf (" Root window id: "); 1305863f95b1Smrg Display_Window_Id (&rw, True); 1306863f95b1Smrg printf (" Parent window id: "); 1307863f95b1Smrg Display_Window_Id (&pw, True); 1308863f95b1Smrg } 1309863f95b1Smrg 1310863f95b1Smrg num_children = xcb_query_tree_children_length (tree); 1311ff7e0accSmrg 1312863f95b1Smrg if (level == 0 || num_children > 0) { 1313863f95b1Smrg printf (" "); 1314863f95b1Smrg for (j = 0; j < level; j++) printf (" "); 1315863f95b1Smrg printf ("%d child%s%s\n", num_children, num_children == 1 ? "" : "ren", 1316863f95b1Smrg num_children ? ":" : "."); 1317863f95b1Smrg } 1318863f95b1Smrg 1319863f95b1Smrg if (num_children > 0) { 1320863f95b1Smrg xcb_window_t *child_list = xcb_query_tree_children (tree); 1321863f95b1Smrg struct wininfo *children 1322863f95b1Smrg = calloc (num_children, sizeof(struct wininfo)); 1323863f95b1Smrg 1324863f95b1Smrg if (children == NULL) 1325863f95b1Smrg Fatal_Error ("Failed to allocate memory in display_tree_info"); 1326863f95b1Smrg 1327863f95b1Smrg for (i = (int)num_children - 1; i >= 0; i--) { 1328863f95b1Smrg struct wininfo *cw = &children[i]; 1329863f95b1Smrg 1330863f95b1Smrg cw->window = child_list[i]; 1331863f95b1Smrg cw->net_wm_name_cookie = get_net_wm_name (dpy, child_list[i]); 1332853aa076Smrg cw->wm_name_cookie = xcb_icccm_get_wm_name (dpy, child_list[i]); 1333853aa076Smrg cw->wm_class_cookie = xcb_icccm_get_wm_class (dpy, child_list[i]); 1334863f95b1Smrg cw->geometry_cookie = xcb_get_geometry (dpy, child_list[i]); 1335863f95b1Smrg cw->trans_coords_cookie = xcb_translate_coordinates 1336863f95b1Smrg (dpy, child_list[i], tree->root, 0, 0); 1337863f95b1Smrg if (recurse) 1338863f95b1Smrg cw->tree_cookie = xcb_query_tree (dpy, child_list[i]); 1339ff7e0accSmrg } 1340863f95b1Smrg xcb_flush (dpy); 1341863f95b1Smrg 1342863f95b1Smrg for (i = (int)num_children - 1; i >= 0; i--) { 1343863f95b1Smrg struct wininfo *cw = &children[i]; 1344863f95b1Smrg Bool got_wm_class = False; 1345863f95b1Smrg char *instance_name = NULL, *class_name = NULL; 1346863f95b1Smrg int instance_name_len, class_name_len; 1347863f95b1Smrg#ifdef USE_XCB_ICCCM 1348853aa076Smrg xcb_icccm_get_wm_class_reply_t classhint; 1349863f95b1Smrg#else 1350863f95b1Smrg xcb_get_property_reply_t *classprop; 1351863f95b1Smrg#endif 1352863f95b1Smrg xcb_get_geometry_reply_t *geometry; 1353863f95b1Smrg 1354863f95b1Smrg printf (" "); 1355863f95b1Smrg for (j = 0; j < level; j++) printf (" "); 1356863f95b1Smrg Display_Window_Id (cw, False); 1357863f95b1Smrg printf (": ("); 1358863f95b1Smrg 1359863f95b1Smrg#ifdef USE_XCB_ICCCM 1360853aa076Smrg if (xcb_icccm_get_wm_class_reply (dpy, cw->wm_class_cookie, 1361863f95b1Smrg &classhint, NULL)) { 1362863f95b1Smrg got_wm_class = True; 1363863f95b1Smrg instance_name = classhint.instance_name; 1364863f95b1Smrg class_name = classhint.class_name; 1365863f95b1Smrg instance_name_len = strlen(instance_name); 1366863f95b1Smrg class_name_len = strlen(class_name); 1367863f95b1Smrg } 1368863f95b1Smrg#else 1369863f95b1Smrg classprop = xcb_get_property_reply 1370863f95b1Smrg (dpy, cw->wm_class_cookie, NULL); 1371863f95b1Smrg if (classprop) { 1372863f95b1Smrg if (classprop->type == XCB_ATOM_STRING && 1373863f95b1Smrg classprop->format == 8) { 1374863f95b1Smrg int proplen = xcb_get_property_value_length (classprop); 1375863f95b1Smrg 1376863f95b1Smrg instance_name = xcb_get_property_value (classprop); 1377863f95b1Smrg instance_name_len = strnlen (instance_name, proplen); 1378863f95b1Smrg if (instance_name_len < proplen) { 1379863f95b1Smrg class_name = instance_name + instance_name_len + 1; 1380863f95b1Smrg class_name_len = strnlen 1381863f95b1Smrg (class_name, proplen - (instance_name_len + 1)); 1382863f95b1Smrg } else 1383863f95b1Smrg class_name_len = 0; 1384863f95b1Smrg got_wm_class = True; 1385863f95b1Smrg } 1386863f95b1Smrg else 1387863f95b1Smrg free (classprop); 1388863f95b1Smrg } 1389863f95b1Smrg#endif 1390863f95b1Smrg 1391863f95b1Smrg if (got_wm_class) { 1392863f95b1Smrg if (instance_name) 1393863f95b1Smrg printf ("\"%.*s\" ", instance_name_len, instance_name); 1394863f95b1Smrg else 1395863f95b1Smrg printf ("(none) "); 1396863f95b1Smrg 1397863f95b1Smrg if (class_name) 1398863f95b1Smrg printf ("\"%.*s\") ", class_name_len, class_name); 1399863f95b1Smrg else 1400863f95b1Smrg printf ("(none)) "); 1401863f95b1Smrg 1402863f95b1Smrg#ifdef USE_XCB_ICCCM 1403853aa076Smrg xcb_icccm_get_wm_class_reply_wipe (&classhint); 1404863f95b1Smrg#else 1405863f95b1Smrg free (classprop); 1406863f95b1Smrg#endif 1407863f95b1Smrg } else 1408863f95b1Smrg printf (") "); 1409863f95b1Smrg 1410863f95b1Smrg geometry = xcb_get_geometry_reply(dpy, cw->geometry_cookie, &err); 1411863f95b1Smrg if (geometry) { 1412863f95b1Smrg xcb_translate_coordinates_reply_t *trans_coords; 1413863f95b1Smrg 1414863f95b1Smrg printf (" %ux%u+%d+%d", geometry->width, geometry->height, 1415863f95b1Smrg geometry->x, geometry->y); 1416863f95b1Smrg 1417863f95b1Smrg trans_coords = xcb_translate_coordinates_reply 1418863f95b1Smrg (dpy, cw->trans_coords_cookie, &err); 1419863f95b1Smrg 1420863f95b1Smrg if (trans_coords) { 1421863f95b1Smrg int16_t abs_x = (int16_t) trans_coords->dst_x; 1422863f95b1Smrg int16_t abs_y = (int16_t) trans_coords->dst_y; 1423863f95b1Smrg int border = geometry->border_width; 1424863f95b1Smrg 1425863f95b1Smrg printf (" +%d+%d", abs_x - border, abs_y - border); 1426863f95b1Smrg free (trans_coords); 1427863f95b1Smrg } else if (err) { 1428863f95b1Smrg Print_X_Error (dpy, err); 1429863f95b1Smrg } 1430863f95b1Smrg 1431863f95b1Smrg free (geometry); 1432863f95b1Smrg } else if (err) { 1433863f95b1Smrg Print_X_Error (dpy, err); 1434863f95b1Smrg } 1435863f95b1Smrg printf ("\n"); 1436863f95b1Smrg 1437863f95b1Smrg if (recurse) 1438863f95b1Smrg display_tree_info_1 (cw, 1, level+1); 1439863f95b1Smrg 1440863f95b1Smrg wininfo_wipe (cw); 1441863f95b1Smrg } 1442863f95b1Smrg free (children); 1443ff7e0accSmrg } 1444ff7e0accSmrg 1445863f95b1Smrg free (tree); /* includes storage for child_list[] */ 1446ff7e0accSmrg} 1447ff7e0accSmrg 1448ff7e0accSmrg 1449ff7e0accSmrg/* 1450ff7e0accSmrg * Display a set of size hints 1451ff7e0accSmrg */ 1452ff7e0accSmrgstatic void 1453863f95b1SmrgDisplay_Hints (xcb_size_hints_t *hints) 1454ff7e0accSmrg{ 1455863f95b1Smrg long flags; 1456ff7e0accSmrg 1457863f95b1Smrg flags = hints->flags; 1458ff7e0accSmrg 1459853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_US_POSITION) 1460863f95b1Smrg printf (" User supplied location: %s, %s\n", 1461863f95b1Smrg xscale (hints->x), yscale (hints->y)); 1462ff7e0accSmrg 1463853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_POSITION) 1464863f95b1Smrg printf (" Program supplied location: %s, %s\n", 1465863f95b1Smrg xscale (hints->x), yscale (hints->y)); 1466ff7e0accSmrg 1467853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_US_SIZE) { 1468863f95b1Smrg printf (" User supplied size: %s by %s\n", 1469863f95b1Smrg xscale (hints->width), yscale (hints->height)); 1470863f95b1Smrg } 1471ff7e0accSmrg 1472853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_SIZE) 1473863f95b1Smrg printf (" Program supplied size: %s by %s\n", 1474863f95b1Smrg xscale (hints->width), yscale (hints->height)); 1475ff7e0accSmrg 1476853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) 1477863f95b1Smrg printf (" Program supplied minimum size: %s by %s\n", 1478863f95b1Smrg xscale (hints->min_width), yscale (hints->min_height)); 1479ff7e0accSmrg 1480853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) 1481863f95b1Smrg printf (" Program supplied maximum size: %s by %s\n", 1482863f95b1Smrg xscale (hints->max_width), yscale (hints->max_height)); 1483ff7e0accSmrg 1484853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) { 1485863f95b1Smrg printf (" Program supplied base size: %s by %s\n", 1486863f95b1Smrg xscale (hints->base_width), yscale (hints->base_height)); 1487863f95b1Smrg } 1488863f95b1Smrg 1489853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC) { 1490863f95b1Smrg printf (" Program supplied x resize increment: %s\n", 1491863f95b1Smrg xscale (hints->width_inc)); 1492863f95b1Smrg printf (" Program supplied y resize increment: %s\n", 1493863f95b1Smrg yscale (hints->height_inc)); 1494863f95b1Smrg if (hints->width_inc != 0 && hints->height_inc != 0) { 1495853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_US_SIZE) 1496863f95b1Smrg printf (" User supplied size in resize increments: %s by %s\n", 1497863f95b1Smrg (xscale (hints->width / hints->width_inc)), 1498863f95b1Smrg (yscale (hints->height / hints->height_inc))); 1499853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_SIZE) 1500863f95b1Smrg printf (" Program supplied size in resize increments: %s by %s\n", 1501863f95b1Smrg (xscale (hints->width / hints->width_inc)), 1502863f95b1Smrg (yscale (hints->height / hints->height_inc))); 1503853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) 1504863f95b1Smrg printf (" Program supplied minimum size in resize increments: %s by %s\n", 1505863f95b1Smrg xscale (hints->min_width / hints->width_inc), yscale (hints->min_height / hints->height_inc)); 1506853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) 1507863f95b1Smrg printf (" Program supplied base size in resize increments: %s by %s\n", 1508863f95b1Smrg (xscale (hints->base_width / hints->width_inc)), 1509863f95b1Smrg (yscale (hints->base_height / hints->height_inc))); 1510ff7e0accSmrg } 1511863f95b1Smrg } 1512863f95b1Smrg 1513853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_ASPECT) { 1514863f95b1Smrg printf (" Program supplied min aspect ratio: %s/%s\n", 1515863f95b1Smrg xscale (hints->min_aspect_num), yscale (hints->min_aspect_den)); 1516863f95b1Smrg printf (" Program supplied max aspect ratio: %s/%s\n", 1517863f95b1Smrg xscale (hints->max_aspect_num), yscale (hints->max_aspect_den)); 1518863f95b1Smrg } 1519863f95b1Smrg 1520853aa076Smrg if (flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY) { 1521863f95b1Smrg printf (" Program supplied window gravity: %s\n", 1522863f95b1Smrg Lookup (hints->win_gravity, _gravities)); 1523863f95b1Smrg } 1524ff7e0accSmrg} 1525ff7e0accSmrg 1526ff7e0accSmrg 1527ff7e0accSmrg/* 1528ff7e0accSmrg * Display Size Hints info 1529ff7e0accSmrg */ 1530ff7e0accSmrgstatic void 1531863f95b1SmrgDisplay_Size_Hints (struct wininfo *w) 1532ff7e0accSmrg{ 1533863f95b1Smrg xcb_size_hints_t hints; 1534ff7e0accSmrg 1535863f95b1Smrg printf ("\n"); 1536863f95b1Smrg if (!fetch_normal_hints (w, &hints)) 1537863f95b1Smrg printf (" No normal window size hints defined\n"); 1538863f95b1Smrg else { 1539863f95b1Smrg printf (" Normal window size hints:\n"); 1540863f95b1Smrg Display_Hints (&hints); 1541863f95b1Smrg } 1542863f95b1Smrg 1543853aa076Smrg if (!xcb_icccm_get_wm_size_hints_reply (dpy, w->zoom_cookie, &hints, NULL)) 1544863f95b1Smrg printf (" No zoom window size hints defined\n"); 1545863f95b1Smrg else { 1546863f95b1Smrg printf (" Zoom window size hints:\n"); 1547863f95b1Smrg Display_Hints (&hints); 1548863f95b1Smrg } 1549ff7e0accSmrg} 1550ff7e0accSmrg 1551ff7e0accSmrg 1552ff7e0accSmrgstatic void 1553863f95b1SmrgDisplay_Window_Shape (xcb_window_t window) 1554ff7e0accSmrg{ 1555863f95b1Smrg const xcb_query_extension_reply_t *shape_query; 1556863f95b1Smrg xcb_shape_query_extents_cookie_t extents_cookie; 1557863f95b1Smrg xcb_shape_query_extents_reply_t *extents; 1558ff7e0accSmrg 1559863f95b1Smrg shape_query = xcb_get_extension_data (dpy, &xcb_shape_id); 1560863f95b1Smrg if (!shape_query->present) 1561ff7e0accSmrg return; 1562ff7e0accSmrg 1563863f95b1Smrg printf ("\n"); 1564863f95b1Smrg 1565863f95b1Smrg extents_cookie = xcb_shape_query_extents (dpy, window); 1566863f95b1Smrg extents = xcb_shape_query_extents_reply (dpy, extents_cookie, &err); 1567863f95b1Smrg 1568863f95b1Smrg if (!extents) { 1569863f95b1Smrg if (err) 1570863f95b1Smrg Print_X_Error (dpy, err); 1571863f95b1Smrg else 1572863f95b1Smrg { 1573863f95b1Smrg printf (" No window shape defined\n"); 1574863f95b1Smrg printf (" No border shape defined\n"); 1575863f95b1Smrg } 1576863f95b1Smrg return; 1577863f95b1Smrg } 1578863f95b1Smrg 1579863f95b1Smrg if (!extents->bounding_shaped) 1580863f95b1Smrg printf (" No window shape defined\n"); 1581ff7e0accSmrg else { 1582863f95b1Smrg printf (" Window shape extents: %sx%s", 1583863f95b1Smrg xscale (extents->bounding_shape_extents_width), 1584863f95b1Smrg yscale (extents->bounding_shape_extents_height)); 1585863f95b1Smrg printf ("+%s+%s\n", 1586863f95b1Smrg xscale (extents->bounding_shape_extents_x), 1587863f95b1Smrg yscale (extents->bounding_shape_extents_y)); 1588ff7e0accSmrg } 1589863f95b1Smrg if (!extents->clip_shaped) 1590863f95b1Smrg printf (" No border shape defined\n"); 1591ff7e0accSmrg else { 1592863f95b1Smrg printf (" Border shape extents: %sx%s", 1593863f95b1Smrg xscale (extents->clip_shape_extents_width), 1594863f95b1Smrg yscale (extents->clip_shape_extents_height)); 1595863f95b1Smrg printf ("+%s+%s\n", 1596863f95b1Smrg xscale (extents->clip_shape_extents_x), 1597863f95b1Smrg yscale (extents->clip_shape_extents_y)); 1598ff7e0accSmrg } 1599863f95b1Smrg 1600863f95b1Smrg free (extents); 1601ff7e0accSmrg} 1602ff7e0accSmrg 1603ff7e0accSmrg/* 1604ff7e0accSmrg * Display Window Manager Info 1605863f95b1Smrg * 1606863f95b1Smrg * Requires wininfo members initialized: 1607863f95b1Smrg * window, hints_cookie 1608ff7e0accSmrg */ 1609ff7e0accSmrgstatic const binding _state_hints[] = { 1610853aa076Smrg { XCB_ICCCM_WM_STATE_WITHDRAWN, "Withdrawn State" }, 1611853aa076Smrg { XCB_ICCCM_WM_STATE_NORMAL, "Normal State" }, 1612853aa076Smrg { XCB_ICCCM_WM_STATE_ICONIC, "Iconic State" }, 1613863f95b1Smrg/* xwininfo previously also reported the ZoomState & InactiveState, 1614863f95b1Smrg but ICCCM declared those obsolete long ago */ 161510998002Smrg { 0, NULL } }; 1616ff7e0accSmrg 1617863f95b1Smrg#ifndef USE_XCB_ICCCM 1618863f95b1Smrgstatic Bool 1619cf2cd791Smrgwm_hints_reply (xcb_connection_t *whr_dpy, xcb_get_property_cookie_t cookie, 1620cf2cd791Smrg wm_hints_t *hints_return, xcb_generic_error_t **whr_err) 1621863f95b1Smrg{ 1622cf2cd791Smrg xcb_get_property_reply_t *prop = xcb_get_property_reply (whr_dpy, cookie, whr_err); 1623e8f4a63fSmrg size_t length; 1624863f95b1Smrg 1625863f95b1Smrg if (!prop || (prop->type != XCB_ATOM_WM_HINTS) || (prop->format != 32)) { 1626863f95b1Smrg free (prop); 1627863f95b1Smrg return False; 1628863f95b1Smrg } 1629863f95b1Smrg 1630863f95b1Smrg memset (hints_return, 0, sizeof(wm_hints_t)); 1631863f95b1Smrg 1632e8f4a63fSmrg length = (size_t) xcb_get_property_value_length(prop); 1633863f95b1Smrg if (length > sizeof(wm_hints_t)) 1634863f95b1Smrg length = sizeof(wm_hints_t); 1635863f95b1Smrg memcpy (hints_return, xcb_get_property_value (prop), length); 1636863f95b1Smrg 1637863f95b1Smrg free (prop); 1638863f95b1Smrg return True; 1639863f95b1Smrg} 1640863f95b1Smrg 1641853aa076Smrg#define xcb_icccm_get_wm_hints_reply wm_hints_reply 1642863f95b1Smrg#endif 1643863f95b1Smrg 1644cf2cd791Smrgstatic void 1645cf2cd791SmrgDisplay_Atom_Name (xcb_atom_t atom, const char *prefix) 1646cf2cd791Smrg{ 1647cf2cd791Smrg const char *atom_name = Get_Atom_Name (dpy, atom); 1648cf2cd791Smrg 1649cf2cd791Smrg if (atom_name) { 1650cf2cd791Smrg char *friendly_name = get_friendly_name (atom_name, prefix); 1651cf2cd791Smrg printf (" %s\n", friendly_name); 1652cf2cd791Smrg free (friendly_name); 1653cf2cd791Smrg } else { 1654cf2cd791Smrg printf (" (unresolvable ATOM 0x%x)\n", atom); 1655cf2cd791Smrg } 1656cf2cd791Smrg} 1657cf2cd791Smrg 1658ff7e0accSmrgstatic void 1659863f95b1SmrgDisplay_WM_Info (struct wininfo *w) 1660ff7e0accSmrg{ 1661853aa076Smrg xcb_icccm_wm_hints_t wmhints; 1662863f95b1Smrg long flags; 1663863f95b1Smrg xcb_get_property_reply_t *prop; 1664863f95b1Smrg int i; 1665863f95b1Smrg 1666863f95b1Smrg printf ("\n"); 1667853aa076Smrg if (!xcb_icccm_get_wm_hints_reply(dpy, w->hints_cookie, &wmhints, &err)) 1668863f95b1Smrg { 1669863f95b1Smrg printf (" No window manager hints defined\n"); 1670863f95b1Smrg if (err) 1671863f95b1Smrg Print_X_Error (dpy, err); 1672863f95b1Smrg flags = 0; 1673863f95b1Smrg } else 1674863f95b1Smrg flags = wmhints.flags; 1675863f95b1Smrg 1676863f95b1Smrg printf (" Window manager hints:\n"); 1677863f95b1Smrg 1678853aa076Smrg if (flags & XCB_ICCCM_WM_HINT_INPUT) 1679863f95b1Smrg printf (" Client accepts input or input focus: %s\n", 1680863f95b1Smrg Lookup (wmhints.input, _bool)); 1681863f95b1Smrg 1682853aa076Smrg if (flags & XCB_ICCCM_WM_HINT_ICON_WINDOW) { 1683863f95b1Smrg struct wininfo iw; 1684863f95b1Smrg iw.window = wmhints.icon_window; 1685863f95b1Smrg iw.net_wm_name_cookie = get_net_wm_name (dpy, iw.window); 1686853aa076Smrg iw.wm_name_cookie = xcb_icccm_get_wm_name (dpy, iw.window); 1687863f95b1Smrg 1688863f95b1Smrg printf (" Icon window id: "); 1689863f95b1Smrg Display_Window_Id (&iw, True); 1690863f95b1Smrg } 1691863f95b1Smrg 1692853aa076Smrg if (flags & XCB_ICCCM_WM_HINT_ICON_POSITION) 1693863f95b1Smrg printf (" Initial icon position: %s, %s\n", 1694863f95b1Smrg xscale (wmhints.icon_x), yscale (wmhints.icon_y)); 1695863f95b1Smrg 1696853aa076Smrg if (flags & XCB_ICCCM_WM_HINT_STATE) 1697863f95b1Smrg printf (" Initial state is %s\n", 1698863f95b1Smrg Lookup (wmhints.initial_state, _state_hints)); 1699863f95b1Smrg 1700863f95b1Smrg if (atom_net_wm_desktop) { 1701863f95b1Smrg prop = xcb_get_property_reply (dpy, w->wm_desktop_cookie, NULL); 1702863f95b1Smrg if (prop && (prop->type != XCB_NONE)) { 1703863f95b1Smrg uint32_t *desktop = xcb_get_property_value (prop); 1704863f95b1Smrg if (*desktop == 0xFFFFFFFF) { 1705863f95b1Smrg printf (" Displayed on all desktops\n"); 1706863f95b1Smrg } else { 1707863f95b1Smrg printf (" Displayed on desktop %d\n", *desktop); 1708863f95b1Smrg } 1709ff7e0accSmrg } 1710863f95b1Smrg free (prop); 1711863f95b1Smrg } 1712ff7e0accSmrg 1713863f95b1Smrg if (atom_net_wm_window_type) { 1714863f95b1Smrg prop = xcb_get_property_reply (dpy, w->wm_window_type_cookie, 1715863f95b1Smrg NULL); 1716863f95b1Smrg if (prop && (prop->type != XCB_NONE) && (prop->value_len > 0)) { 1717863f95b1Smrg xcb_atom_t *atoms = xcb_get_property_value (prop); 1718863f95b1Smrg int atom_count = prop->value_len; 1719863f95b1Smrg 1720863f95b1Smrg if (atom_count > 0) { 1721863f95b1Smrg printf (" Window type:\n"); 1722cf2cd791Smrg for (i = 0; i < atom_count; i++) 1723cf2cd791Smrg Display_Atom_Name (atoms[i], "_NET_WM_WINDOW_TYPE_"); 1724863f95b1Smrg } 1725863f95b1Smrg } 1726863f95b1Smrg free (prop); 1727863f95b1Smrg } 1728863f95b1Smrg 1729863f95b1Smrg if (atom_net_wm_state) { 1730863f95b1Smrg prop = xcb_get_property_reply (dpy, w->wm_state_cookie, NULL); 1731863f95b1Smrg if (prop && (prop->type != XCB_NONE) && (prop->value_len > 0)) { 1732863f95b1Smrg xcb_atom_t *atoms = xcb_get_property_value (prop); 1733863f95b1Smrg int atom_count = prop->value_len; 1734863f95b1Smrg 1735863f95b1Smrg if (atom_count > 0) { 1736863f95b1Smrg printf (" Window state:\n"); 1737cf2cd791Smrg for (i = 0; i < atom_count; i++) 1738cf2cd791Smrg Display_Atom_Name (atoms[i], "_NET_WM_STATE_"); 1739863f95b1Smrg } 1740863f95b1Smrg } 1741863f95b1Smrg free (prop); 1742863f95b1Smrg } 1743ff7e0accSmrg 1744863f95b1Smrg if (atom_net_wm_pid) { 1745863f95b1Smrg printf (" Process id: "); 1746863f95b1Smrg prop = xcb_get_property_reply (dpy, w->wm_pid_cookie, NULL); 1747863f95b1Smrg if (prop && (prop->type == XCB_ATOM_CARDINAL)) { 1748863f95b1Smrg uint32_t *pid = xcb_get_property_value (prop); 1749863f95b1Smrg printf ("%d", *pid); 1750863f95b1Smrg } else { 1751863f95b1Smrg printf ("(unknown)"); 1752863f95b1Smrg } 1753863f95b1Smrg free (prop); 1754ff7e0accSmrg 1755863f95b1Smrg prop = xcb_get_property_reply (dpy, w->wm_client_machine_cookie, NULL); 1756863f95b1Smrg if (prop && (prop->type == XCB_ATOM_STRING)) { 1757863f95b1Smrg const char *hostname = xcb_get_property_value (prop); 1758863f95b1Smrg int hostname_len = xcb_get_property_value_length (prop); 1759863f95b1Smrg printf (" on host %.*s", hostname_len, hostname); 1760ff7e0accSmrg } 1761863f95b1Smrg printf ("\n"); 1762863f95b1Smrg free (prop); 1763863f95b1Smrg } 1764863f95b1Smrg 1765863f95b1Smrg if (atom_net_frame_extents) { 1766863f95b1Smrg prop = xcb_get_property_reply (dpy, w->frame_extents_cookie, NULL); 1767863f95b1Smrg if (prop && (prop->type == XCB_ATOM_CARDINAL) 1768863f95b1Smrg && (prop->value_len == 4)) { 1769863f95b1Smrg uint32_t *extents = xcb_get_property_value (prop); 1770863f95b1Smrg 1771863f95b1Smrg printf (" Frame extents: %d, %d, %d, %d\n", 1772863f95b1Smrg extents[0], extents[1], extents[2], extents[3]); 1773863f95b1Smrg } 1774863f95b1Smrg free (prop); 1775863f95b1Smrg } 1776863f95b1Smrg} 1777863f95b1Smrg 1778863f95b1Smrg/* Frees all members of a wininfo struct, but not the struct itself */ 1779863f95b1Smrgstatic void 1780863f95b1Smrgwininfo_wipe (struct wininfo *w) 1781863f95b1Smrg{ 1782863f95b1Smrg free (w->geometry); 1783863f95b1Smrg free (w->win_attributes); 1784863f95b1Smrg free (w->normal_hints); 1785863f95b1Smrg} 1786863f95b1Smrg 1787863f95b1Smrg/* Gets UTF-8 encoded EMWH property _NET_WM_NAME for a window */ 1788863f95b1Smrgstatic xcb_get_property_cookie_t 1789cf2cd791Smrgget_net_wm_name (xcb_connection_t *gnwn_dpy, xcb_window_t win) 1790863f95b1Smrg{ 1791863f95b1Smrg if (!atom_net_wm_name) 1792cf2cd791Smrg atom_net_wm_name = Get_Atom (gnwn_dpy, "_NET_WM_NAME"); 1793863f95b1Smrg 1794863f95b1Smrg if (!atom_utf8_string) 1795cf2cd791Smrg atom_utf8_string = Get_Atom (gnwn_dpy, "UTF8_STRING"); 1796863f95b1Smrg 1797863f95b1Smrg if (atom_net_wm_name && atom_utf8_string) 1798cf2cd791Smrg return xcb_get_property (gnwn_dpy, False, win, atom_net_wm_name, 1799863f95b1Smrg atom_utf8_string, 0, BUFSIZ); 1800863f95b1Smrg else { 1801863f95b1Smrg xcb_get_property_cookie_t dummy = { 0 }; 1802863f95b1Smrg return dummy; 1803863f95b1Smrg } 1804863f95b1Smrg} 1805863f95b1Smrg 1806863f95b1Smrg/* [Copied from code added by Yang Zhao to xprop/xprop.c] 1807863f95b1Smrg * 1808863f95b1Smrg * Validate a string as UTF-8 encoded according to RFC 3629 1809863f95b1Smrg * 1810863f95b1Smrg * Simply, a unicode code point (up to 21-bits long) is encoded as follows: 1811863f95b1Smrg * 1812863f95b1Smrg * Char. number range | UTF-8 octet sequence 1813863f95b1Smrg * (hexadecimal) | (binary) 1814863f95b1Smrg * --------------------+--------------------------------------------- 1815863f95b1Smrg * 0000 0000-0000 007F | 0xxxxxxx 1816863f95b1Smrg * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 1817863f95b1Smrg * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 1818863f95b1Smrg * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 1819863f95b1Smrg * 1820863f95b1Smrg * Validation is done left-to-right, and an error condition, if any, refers to 1821863f95b1Smrg * only the left-most problem in the string. 1822863f95b1Smrg * 1823863f95b1Smrg * Return values: 1824863f95b1Smrg * UTF8_VALID: Valid UTF-8 encoded string 1825863f95b1Smrg * UTF8_OVERLONG: Using more bytes than needed for a code point 1826863f95b1Smrg * UTF8_SHORT_TAIL: Not enough bytes in a multi-byte sequence 1827863f95b1Smrg * UTF8_LONG_TAIL: Too many bytes in a multi-byte sequence 1828863f95b1Smrg * UTF8_FORBIDDEN_VALUE: Forbidden prefix or code point outside 0x10FFFF 1829863f95b1Smrg */ 1830863f95b1Smrg#define UTF8_VALID 0 1831863f95b1Smrg#define UTF8_FORBIDDEN_VALUE 1 1832863f95b1Smrg#define UTF8_OVERLONG 2 1833863f95b1Smrg#define UTF8_SHORT_TAIL 3 1834863f95b1Smrg#define UTF8_LONG_TAIL 4 1835863f95b1Smrgstatic int 1836cf2cd791Smrgis_valid_utf8 (const char *string, size_t len) 1837863f95b1Smrg{ 1838863f95b1Smrg unsigned long codepoint; 1839e8f4a63fSmrg int rem; 1840e8f4a63fSmrg size_t i; 1841863f95b1Smrg unsigned char c; 1842863f95b1Smrg 1843863f95b1Smrg rem = 0; 1844863f95b1Smrg for (i = 0; i < len; i++) { 1845863f95b1Smrg c = (unsigned char) string[i]; 1846863f95b1Smrg 1847863f95b1Smrg /* Order of type check: 1848863f95b1Smrg * - Single byte code point 1849863f95b1Smrg * - Non-starting byte of multi-byte sequence 1850863f95b1Smrg * - Start of 2-byte sequence 1851863f95b1Smrg * - Start of 3-byte sequence 1852863f95b1Smrg * - Start of 4-byte sequence 1853863f95b1Smrg */ 1854863f95b1Smrg if (!(c & 0x80)) { 1855863f95b1Smrg if (rem > 0) return UTF8_SHORT_TAIL; 1856863f95b1Smrg rem = 0; 1857863f95b1Smrg codepoint = c; 1858863f95b1Smrg } else if ((c & 0xC0) == 0x80) { 1859863f95b1Smrg if (rem == 0) return UTF8_LONG_TAIL; 1860863f95b1Smrg rem--; 1861863f95b1Smrg codepoint |= (c & 0x3F) << (rem * 6); 1862863f95b1Smrg if (codepoint == 0) return UTF8_OVERLONG; 1863863f95b1Smrg } else if ((c & 0xE0) == 0xC0) { 1864863f95b1Smrg if (rem > 0) return UTF8_SHORT_TAIL; 1865863f95b1Smrg rem = 1; 1866863f95b1Smrg codepoint = (c & 0x1F) << 6; 1867863f95b1Smrg if (codepoint == 0) return UTF8_OVERLONG; 1868863f95b1Smrg } else if ((c & 0xF0) == 0xE0) { 1869863f95b1Smrg if (rem > 0) return UTF8_SHORT_TAIL; 1870863f95b1Smrg rem = 2; 1871863f95b1Smrg codepoint = (c & 0x0F) << 12; 1872863f95b1Smrg } else if ((c & 0xF8) == 0xF0) { 1873863f95b1Smrg if (rem > 0) return UTF8_SHORT_TAIL; 1874863f95b1Smrg rem = 3; 1875863f95b1Smrg codepoint = (c & 0x07) << 18; 1876863f95b1Smrg if (codepoint > 0x10FFFF) return UTF8_FORBIDDEN_VALUE; 1877863f95b1Smrg } else 1878863f95b1Smrg return UTF8_FORBIDDEN_VALUE; 1879863f95b1Smrg } 1880ff7e0accSmrg 1881863f95b1Smrg return UTF8_VALID; 1882863f95b1Smrg} 1883863f95b1Smrg 1884863f95b1Smrg/* 1885863f95b1Smrg * Converts a UTF-8 encoded string to the current locale encoding, 1886863f95b1Smrg * if possible, and prints it, with prefix before and suffix after. 1887863f95b1Smrg * Length of the string is specified in bytes, or -1 for going until '\0' 1888863f95b1Smrg */ 1889863f95b1Smrgstatic void 1890cf2cd791Smrgprint_utf8 (const char *prefix, const char *u8str, size_t length, const char *suffix) 1891863f95b1Smrg{ 1892863f95b1Smrg size_t inlen = length; 1893863f95b1Smrg 1894863f95b1Smrg if (is_valid_utf8 (u8str, inlen) != UTF8_VALID) { 1895863f95b1Smrg printf (" (invalid UTF8_STRING)"); 1896863f95b1Smrg return; 1897863f95b1Smrg } 1898863f95b1Smrg 1899863f95b1Smrg if (strcmp (user_encoding, "UTF-8") == 0) { 1900863f95b1Smrg /* Don't need to convert */ 1901863f95b1Smrg printf ("%s", prefix); 1902863f95b1Smrg fwrite (u8str, 1, inlen, stdout); 1903863f95b1Smrg printf ("%s", suffix); 1904863f95b1Smrg return; 1905863f95b1Smrg } 1906863f95b1Smrg 1907863f95b1Smrg#ifdef HAVE_ICONV 1908863f95b1Smrg if (!iconv_from_utf8) { 1909863f95b1Smrg iconv_from_utf8 = iconv_open (user_encoding, "UTF-8"); 1910863f95b1Smrg } 1911863f95b1Smrg 1912863f95b1Smrg if (iconv_from_utf8 != (iconv_t) -1) { 1913863f95b1Smrg Bool done = True; 1914cf2cd791Smrg ICONV_CONST char *inp = u8str; 1915863f95b1Smrg char convbuf[BUFSIZ]; 1916863f95b1Smrg int convres; 1917863f95b1Smrg 1918863f95b1Smrg printf ("%s", prefix); 1919863f95b1Smrg do { 1920863f95b1Smrg char *outp = convbuf; 1921863f95b1Smrg size_t outlen = sizeof(convbuf); 1922863f95b1Smrg 1923abea39b2Swiz convres = iconv (iconv_from_utf8, &inp, &inlen, &outp, &outlen); 1924ff7e0accSmrg 1925863f95b1Smrg if ((convres == -1) && (errno == E2BIG)) { 1926863f95b1Smrg done = False; 1927863f95b1Smrg convres = 0; 1928863f95b1Smrg } 1929863f95b1Smrg 1930863f95b1Smrg if (convres == 0) { 1931863f95b1Smrg fwrite (convbuf, 1, sizeof(convbuf) - outlen, stdout); 1932863f95b1Smrg } else { 1933863f95b1Smrg printf (" (failure in conversion from UTF8_STRING to %s)", 1934863f95b1Smrg user_encoding); 1935863f95b1Smrg } 1936863f95b1Smrg } while (!done); 1937863f95b1Smrg printf ("%s", suffix); 1938863f95b1Smrg } else { 1939863f95b1Smrg printf (" (can't load iconv conversion for UTF8_STRING to %s)", 1940863f95b1Smrg user_encoding); 1941863f95b1Smrg } 1942863f95b1Smrg#else 1943863f95b1Smrg printf (" (can't convert UTF8_STRING to %s)", user_encoding); 1944863f95b1Smrg#endif 1945863f95b1Smrg} 1946863f95b1Smrg 1947863f95b1Smrg/* 1948863f95b1Smrg * Takes a string such as an atom name, strips the prefix, converts 1949863f95b1Smrg * underscores to spaces, lowercases all but the first letter of each word, 1950cf2cd791Smrg * and returns it. The returned string should be freed by the caller. 1951863f95b1Smrg */ 1952cf2cd791Smrgstatic char * 1953cf2cd791Smrgget_friendly_name (const char *string, const char *prefix) 1954863f95b1Smrg{ 1955863f95b1Smrg const char *name_start = string; 1956863f95b1Smrg char *lowered_name, *n; 1957cf2cd791Smrg Bool first = True; 1958cf2cd791Smrg size_t prefix_len = strlen (prefix); 1959863f95b1Smrg 1960863f95b1Smrg if (strncmp (name_start, prefix, prefix_len) == 0) { 1961863f95b1Smrg name_start += prefix_len; 1962863f95b1Smrg } 1963863f95b1Smrg 1964863f95b1Smrg lowered_name = strdup (name_start); 1965cf2cd791Smrg if (lowered_name == NULL) 1966cf2cd791Smrg Fatal_Error ("Failed to allocate memory in get_friendly_name"); 1967cf2cd791Smrg 1968cf2cd791Smrg for (n = lowered_name ; *n != 0 ; n++) { 1969cf2cd791Smrg if (*n == '_') { 1970cf2cd791Smrg *n = ' '; 1971cf2cd791Smrg first = True; 1972cf2cd791Smrg } else if (first) { 1973cf2cd791Smrg first = False; 1974cf2cd791Smrg } else { 1975cf2cd791Smrg *n = tolower((unsigned char)*n); 1976863f95b1Smrg } 1977863f95b1Smrg } 1978ff7e0accSmrg 1979cf2cd791Smrg return lowered_name; 1980ff7e0accSmrg} 1981