diff options
author | Jérémie Courrèges-Anglas <jca@wxcvbn.org> | 2013-02-06 19:50:53 +0100 |
---|---|---|
committer | Jérémie Courrèges-Anglas <jca@wxcvbn.org> | 2013-02-06 21:17:52 +0100 |
commit | 20c5d11a3be2843c808ba84f971ed3fed011e144 (patch) | |
tree | a384626ed4d274bef782a762efabc775734b716a | |
parent | 3725c23fddd8e936a91296f74e3fd6342270d6bb (diff) | |
download | ratpoison-20c5d11a3be2843c808ba84f971ed3fed011e144.zip |
use utf8-handling Xft functions if we are in an UTF-8 locale
* (manage.c) in get_wmname(), try to get the (UTF-8 encoded)
_NET_WM_NAME property. Fallback to GetWMName() if unavailable.
Add some debugging bits to see which TEXT encoding clients use
for WM_NAME.
* (globals.c) use Xft*Utf8 functions to compute text width and
draw strings. No regressions with or without Xft, UTF-8 locale
or not.
* assume we can use Xft*Utf8 functions whenever we have Xft,
to reduce the #ifdef dance
Original patch from Bernhard R. Link
-rw-r--r-- | src/globals.c | 45 | ||||
-rw-r--r-- | src/manage.c | 88 |
2 files changed, 111 insertions, 22 deletions
diff --git a/src/globals.c b/src/globals.c index 8824484..fda69bf 100644 --- a/src/globals.c +++ b/src/globals.c @@ -280,7 +280,8 @@ init_globals (void) /* Wrapper font functions to support Xft */ void -rp_draw_string (rp_screen *s, Drawable d, int style, int x, int y, char *string, int length) +rp_draw_string (rp_screen *s, Drawable d, int style, int x, int y, + char *string, int length) { if (length < 0) length = strlen (string); @@ -291,22 +292,37 @@ rp_draw_string (rp_screen *s, Drawable d, int style, int x, int y, char *string, XftDraw *draw; draw = XftDrawCreate (dpy, d, DefaultVisual (dpy, s->screen_num), DefaultColormap (dpy, s->screen_num)); - if (draw) - { - XftDrawString8 (draw, style == STYLE_NORMAL ? &s->xft_fg_color:&s->xft_bg_color, s->xft_font, x, y, (FcChar8*) string, length); - XftDrawDestroy (draw); - } + if (!draw) + { + PRINT_ERROR (("Failed to allocate XftDraw object\n")); + return; + } + + if (defaults.utf8_locale) + { + XftDrawStringUtf8 (draw, style == STYLE_NORMAL ? &s->xft_fg_color : + &s->xft_bg_color, s->xft_font, x, y, + (FcChar8*) string, length); + } else - PRINT_ERROR(("Failed to allocate XftDraw object\n")); + { + XftDrawString8 (draw, style == STYLE_NORMAL ? &s->xft_fg_color : + &s->xft_bg_color, s->xft_font, x, y, + (FcChar8*) string, length); + } + XftDrawDestroy (draw); } else + PRINT_ERROR (("No Xft font available.\n")); +#else + XmbDrawString (dpy, d, defaults.font, style == STYLE_NORMAL ? s->normal_gc : + s->inverse_gc, x, y, string, length); #endif - XmbDrawString (dpy, d, defaults.font, style == STYLE_NORMAL ? s->normal_gc:s->inverse_gc, x, y, string, length); } int #ifdef USE_XFT_FONT -rp_text_width (rp_screen *s, XFontSet font, char *string, int count) +rp_text_width (rp_screen *s, XFontSet font UNUSED, char *string, int count) #else rp_text_width (rp_screen *s UNUSED, XFontSet font, char *string, int count) #endif @@ -318,11 +334,16 @@ rp_text_width (rp_screen *s UNUSED, XFontSet font, char *string, int count) if (s->xft_font) { XGlyphInfo extents; - XftTextExtents8 (dpy, s->xft_font, (FcChar8*) string, count, &extents); + if (defaults.utf8_locale) + XftTextExtentsUtf8 (dpy, s->xft_font, (FcChar8*) string, count, &extents); + else + XftTextExtents8 (dpy, s->xft_font, (FcChar8*) string, count, &extents); return extents.xOff; } - else + PRINT_ERROR (("No Xft font available.\n")); + return 0; +#else + return XmbTextEscapement (font, string, count); #endif - return XmbTextEscapement (font, string, count); } diff --git a/src/manage.c b/src/manage.c index f822c53..49e7b75 100644 --- a/src/manage.c +++ b/src/manage.c @@ -200,24 +200,92 @@ get_wmname (Window w) { char *name = NULL; XTextProperty text_prop; - int status, n; + int ret = None, n; char** cl; - if (XGetWMName(dpy, w, &text_prop) != 0) { - status = XmbTextPropertyToTextList(dpy, &text_prop, &cl, &n); - if (status == Success && cl && n > 0) { - name = xstrdup(cl[0]); - XFreeStringList(cl); - } else if (text_prop.encoding == XA_STRING) { - name = xstrdup((char*)text_prop.value); + /* If current encoding is UTF-8, try to use the window's _NET_WM_NAME ewmh + property */ + if (defaults.utf8_locale) + { + Atom type = None; + unsigned long nitems, bytes_after; + int format; + char *val = NULL; + + ret = XGetWindowProperty (dpy, w, _net_wm_name, 0, 40, False, + xa_utf8_string, &type, &format, &nitems, + &bytes_after, (unsigned char **) &val); + /* We have a valid UTF-8 string */ + if (ret == Success && type == xa_utf8_string + && format == 8 && nitems > 0) + { + name = xstrdup (val); + XFree (val); + PRINT_DEBUG (("Fetching window name using _NET_WM_NAME succeeded\n")); + PRINT_DEBUG (("WM_NAME: %s\n", name)); + return name; + } + /* Something went wrong for whatever reason */ + if (ret == Success && val) + XFree (val); + PRINT_DEBUG (("Could not fetch window name using _NET_WM_NAME\n")); } - XFree (text_prop.value); - } + + if (XGetWMName (dpy, w, &text_prop) == 0) + { + PRINT_ERROR (("XGetWMName failed\n")); + return NULL; + } + + PRINT_DEBUG (("WM_NAME encoding: ")); + if (text_prop.encoding == xa_string) + PRINT_DEBUG (("STRING\n")); + else if (text_prop.encoding == xa_compound_text) + PRINT_DEBUG (("COMPOUND_TEXT\n")); + else if (text_prop.encoding == xa_utf8_string) + PRINT_DEBUG (("UTF8_STRING\n")); + else + PRINT_DEBUG (("unknown (%d)\n", (int) text_prop.encoding)); + +#ifdef X_HAVE_UTF8_STRING + /* It seems that most applications supporting UTF8_STRING and + _NET_WM_NAME don't bother making their WM_NAME available as + UTF8_STRING (but only as either STRING or COMPOUND_TEXT). + Let's try anyway. */ + if (defaults.utf8_locale && text_prop.encoding == xa_utf8_string) + { + ret = Xutf8TextPropertyToTextList (dpy, &text_prop, &cl, &n); + PRINT_DEBUG (("Xutf8TextPropertyToTextList: %s\n", + ret == Success ? "success" : "error")); + } + else +#endif + { + /* XmbTextPropertyToTextList should be fine for all cases, + even UTF8_STRING encoded WM_NAME */ + ret = XmbTextPropertyToTextList (dpy, &text_prop, &cl, &n); + PRINT_DEBUG (("XmbTextPropertyToTextList: %s\n", + ret == Success ? "success" : "error")); + } + + if (ret == Success && cl && n > 0) + { + name = xstrdup (cl[0]); + XFreeStringList (cl); + } + else if (text_prop.value) + { + /* Convertion failed, try to get the raw string */ + name = xstrdup (text_prop.value); + XFree (text_prop.value); + } + if (name == NULL) { PRINT_DEBUG (("I can't get the WMName.\n")); } else { PRINT_DEBUG (("WM_NAME: '%s'\n", name)); } + return name; } |