[PATCH:xwininfo] Make xcb-icccm dependency be optional and off-by-default
Alan Coopersmith
alan.coopersmith at oracle.com
Fri Jun 25 21:46:34 PDT 2010
Changes to the xcb-icccm API/ABI are under discussion, so for now default
to using local property handling code modeled after the current API, with
a --with-xcb-icccm to enable use of the API for testing/development.
Once the API/ABI is stable & released, this set of changes should be
removed and the xcb-icccm API just used directly.
Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
---
configure.ac | 17 ++++-
dsimple.c | 33 ++++++++-
xwininfo.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 273 insertions(+), 11 deletions(-)
diff --git a/configure.ac b/configure.ac
index 3337c6c..cd7d2a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,8 +40,23 @@ XORG_DEFAULT_OPTIONS
AC_CHECK_FUNCS([strlcat])
+# 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"
+fi
+
# Checks for pkg-config packages
-PKG_CHECK_MODULES(XWININFO, [xcb >= 1.6] xcb-icccm xcb-shape)
+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])
diff --git a/dsimple.c b/dsimple.c
index 95757bd..d06d9a9 100644
--- a/dsimple.c
+++ b/dsimple.c
@@ -48,9 +48,13 @@ from The Open Group.
*/
+#include "config.h"
+
#include <xcb/xcb.h>
#include <xcb/xproto.h>
-#include <xcb/xcb_icccm.h>
+#ifdef USE_XCB_ICCCM
+# include <xcb/xcb_icccm.h>
+#endif
#include <X11/cursorfont.h>
#include <stdio.h>
#include <stdlib.h>
@@ -231,6 +235,12 @@ struct wininfo_cookies {
xcb_query_tree_cookie_t query_tree;
};
+#ifndef USE_XCB_ICCCM
+# define xcb_get_wm_name(Dpy, Win) \
+ xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_NAME, \
+ XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ)
+#endif
+
static xcb_window_t
recursive_Window_With_Name (
xcb_connection_t *dpy,
@@ -243,12 +253,13 @@ recursive_Window_With_Name (
int i;
xcb_window_t w = 0;
char *window_name;
- xcb_get_property_cookie_t get_wm_name_cookie;
xcb_generic_error_t *err;
- xcb_get_text_property_reply_t prop;
xcb_query_tree_reply_t *tree;
struct wininfo_cookies *child_cookies;
+#ifdef USE_XCB_ICCCM
+ xcb_get_text_property_reply_t prop;
+
if (xcb_get_wm_name_reply (dpy, cookies->get_wm_name, &prop, &err)) {
/* can't use strcmp, since prop.name is not null terminated */
if (strncmp (prop.name, name, prop.name_len) == 0) {
@@ -256,6 +267,22 @@ recursive_Window_With_Name (
}
xcb_get_text_property_reply_wipe (&prop);
+#else
+ xcb_get_property_reply_t *prop
+ = xcb_get_property_reply (dpy, cookies->get_wm_name, &err);
+
+ if (prop) {
+ if (prop->type == XCB_ATOM_STRING) {
+ const char *prop_name = xcb_get_property_value (prop);
+ int prop_name_len = xcb_get_property_value_length (prop);
+
+ /* can't use strcmp, since prop.name is not null terminated */
+ if (strncmp (prop_name, name, prop_name_len) == 0) {
+ w = window;
+ }
+ }
+ free (prop);
+#endif
if (w)
{
diff --git a/xwininfo.c b/xwininfo.c
index 7d395df..517346d 100644
--- a/xwininfo.c
+++ b/xwininfo.c
@@ -67,7 +67,9 @@ of the copyright holder.
#include <xcb/xcb.h>
#include <xcb/xproto.h>
-#include <xcb/xcb_icccm.h>
+#ifdef USE_XCB_ICCCM
+# include <xcb/xcb_icccm.h>
+#endif
#include <xcb/shape.h>
#include <stdio.h>
@@ -83,6 +85,99 @@ typedef struct {
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_wm_hints_t wm_hints_t
+
+enum {
+ /* xcb_size_hints_flags_t */
+ XCB_SIZE_HINT_US_POSITION = 1 << 0,
+ XCB_SIZE_HINT_US_SIZE = 1 << 1,
+ XCB_SIZE_HINT_P_POSITION = 1 << 2,
+ XCB_SIZE_HINT_P_SIZE = 1 << 3,
+ XCB_SIZE_HINT_P_MIN_SIZE = 1 << 4,
+ XCB_SIZE_HINT_P_MAX_SIZE = 1 << 5,
+ XCB_SIZE_HINT_P_RESIZE_INC = 1 << 6,
+ XCB_SIZE_HINT_P_ASPECT = 1 << 7,
+ XCB_SIZE_HINT_BASE_SIZE = 1 << 8,
+ XCB_SIZE_HINT_P_WIN_GRAVITY = 1 << 9,
+ /* xcb_wm_state_t */
+ XCB_WM_STATE_WITHDRAWN = 0,
+ XCB_WM_STATE_NORMAL = 1,
+ XCB_WM_STATE_ICONIC = 3,
+ /* xcb_wm_t */
+ XCB_WM_HINT_INPUT = (1L << 0),
+ XCB_WM_HINT_STATE = (1L << 1),
+ XCB_WM_HINT_ICON_PIXMAP = (1L << 2),
+ XCB_WM_HINT_ICON_WINDOW = (1L << 3),
+ XCB_WM_HINT_ICON_POSITION = (1L << 4),
+ XCB_WM_HINT_ICON_MASK = (1L << 5),
+ XCB_WM_HINT_WINDOW_GROUP = (1L << 6),
+ XCB_WM_HINT_X_URGENCY = (1L << 8)
+};
+
+/* Once xcb-icccm's API is stable, these should be replaced by calls to it */
+# define GET_TEXT_PROPERTY(Dpy, Win, Atom) \
+ xcb_get_property (Dpy, False, Win, Atom, XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ)
+# define xcb_get_wm_name(Dpy, Win) GET_TEXT_PROPERTY(Dpy, Win, XCB_ATOM_WM_NAME)
+
+# define xcb_get_wm_class(Dpy, Win) \
+ xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, BUFSIZ)
+# define xcb_get_wm_hints(Dpy, Win) \
+ xcb_get_property(Dpy, False, Win, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9)
+
+# define xcb_get_wm_size_hints(Dpy, Win, Atom) \
+ xcb_get_property (Dpy, False, Win, Atom, XCB_ATOM_WM_SIZE_HINTS, 0, 18)
+# define xcb_get_wm_normal_hints(Dpy, Win) \
+ xcb_get_wm_size_hints(Dpy, Win, XCB_ATOM_WM_NORMAL_HINTS)
+#endif
+
/* Information we keep track of for each window to allow prefetching/reusing */
struct wininfo {
xcb_window_t window;
@@ -505,6 +600,38 @@ fetch_win_attributes (struct wininfo *w)
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);
+ uint32_t flags;
+ 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_get_wm_normal_hints_reply wm_size_hints_reply
+#define xcb_get_wm_size_hints_reply wm_size_hints_reply
+#endif
+
+
+
/* Ensure normal_hints field is filled in */
static xcb_size_hints_t *
fetch_normal_hints (struct wininfo *w, xcb_size_hints_t *hints_return)
@@ -567,8 +694,14 @@ Lookup (int code, const binding *table)
static void
Display_Window_Id (struct wininfo *w, Bool newline_wanted)
{
+#ifdef USE_XCB_ICCCM
xcb_get_text_property_reply_t prop;
+#else
+ xcb_get_property_reply_t *prop;
+#endif
uint8_t got_reply;
+ const char *wm_name;
+ int wm_name_len;
printf (window_id_format, w->window); /* print id # in hex/dec */
@@ -579,18 +712,37 @@ Display_Window_Id (struct wininfo *w, Bool newline_wanted)
printf (" (the root window)");
}
/* Get window name if any */
+#ifdef USE_XCB_ICCCM
got_reply = xcb_get_wm_name_reply (dpy, w->wm_name_cookie,
&prop, NULL);
- if (!got_reply || prop.name_len == 0) {
+ if (got_reply) {
+ wm_name = prop.name;
+ wm_name_len = prop.name_len;
+ }
+#else
+ prop = xcb_get_property_reply (dpy, w->wm_name_cookie, NULL);
+ if (prop && (prop->type == XCB_ATOM_STRING)) {
+ wm_name = xcb_get_property_value (prop);
+ wm_name_len = xcb_get_property_value_length (prop);
+ got_reply = True;
+ } else {
+ got_reply = False;
+ }
+#endif
+ if (!got_reply || wm_name_len == 0) {
printf (" (has no name)");
} else {
printf (" \"");
/* XXX: need to handle encoding */
- printf ("%.*s", prop.name_len, prop.name);
+ printf ("%.*s", wm_name_len, wm_name);
printf ("\"");
}
+#ifdef USE_XCB_ICCCM
if (got_reply)
xcb_get_text_property_reply_wipe (&prop);
+#else
+ free (prop);
+#endif
}
if (newline_wanted)
@@ -1059,7 +1211,14 @@ display_tree_info_1 (struct wininfo *w, int recurse, int level)
for (i = (int)num_children - 1; i >= 0; i--) {
struct wininfo *cw = &children[i];
+ Bool got_wm_class = False;
+ char *instance_name = NULL, *class_name = NULL;
+ int instance_name_len, class_name_len;
+#ifdef USE_XCB_ICCCM
xcb_get_wm_class_reply_t classhint;
+#else
+ xcb_get_property_reply_t *classprop;
+#endif
xcb_get_geometry_reply_t *geometry;
printf (" ");
@@ -1067,19 +1226,53 @@ display_tree_info_1 (struct wininfo *w, int recurse, int level)
Display_Window_Id (cw, False);
printf (": (");
+#ifdef USE_XCB_ICCCM
if (xcb_get_wm_class_reply (dpy, cw->wm_class_cookie,
&classhint, NULL)) {
- if (classhint.instance_name)
- printf ("\"%s\" ", classhint.instance_name);
+ 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));
+ }
+ 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 (classhint.class_name)
- printf ("\"%s\") ", classhint.class_name);
+ if (class_name)
+ printf ("\"%.*s\") ", class_name_len, class_name);
else
printf ("(none)) ");
+#ifdef USE_XCB_ICCCM
xcb_get_wm_class_reply_wipe (&classhint);
+#else
+ free (classprop);
+#endif
} else
printf (") ");
@@ -1290,6 +1483,33 @@ static const binding _state_hints[] = {
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_size_hints_t));
+
+ length = xcb_get_property_value_length(prop);
+ if (length > sizeof(wm_hints_t))
+ length = sizeof(wm_hints_t);
+ memcpy (hints_return, xcb_get_property_value (prop), length);
+
+ free (prop);
+ return True;
+}
+
+#define xcb_get_wm_hints_reply wm_hints_reply
+#endif
+
static void
Display_WM_Info (struct wininfo *w)
{
--
1.5.6.5
More information about the xorg-devel
mailing list