diff options
author | Alan Coopersmith <alan.coopersmith@oracle.com> | 2010-06-25 21:41:21 -0700 |
---|---|---|
committer | Alan Coopersmith <alan.coopersmith@oracle.com> | 2010-07-07 10:47:11 -0700 |
commit | 6ec3573d7876fa62d2a81057ce0d16ed328fad1f (patch) | |
tree | 57e6a45d168c61e410965ed906e6fb61a6a36aa0 | |
parent | 96f19bade9ce4940642d580f4c52e2bc0e3539ab (diff) |
Make xcb-icccm dependency be optional and off-by-default
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@oracle.com>
Reviewed-by: James Cloos <cloos@jhcloos.com>
-rw-r--r-- | configure.ac | 17 | ||||
-rw-r--r-- | dsimple.c | 32 | ||||
-rw-r--r-- | xwininfo.c | 234 |
3 files changed, 273 insertions, 10 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]) @@ -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> @@ -230,6 +234,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, @@ -242,10 +252,12 @@ recursive_Window_With_Name ( int i; xcb_window_t w = 0; 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) { @@ -253,6 +265,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) { @@ -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,37 @@ 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); + 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 +693,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 +711,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) @@ -1060,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 (" "); @@ -1068,19 +1226,54 @@ 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)); + } else + class_name_len = 0; + got_wm_class = True; + } + else + free (classprop); + } +#endif + + if (got_wm_class) { + if (instance_name) + printf ("\"%.*s\" ", instance_name_len, instance_name); else printf ("(none) "); - if (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 (") "); @@ -1291,6 +1484,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_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) { |