From 20c5d11a3be2843c808ba84f971ed3fed011e144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 6 Feb 2013 19:50:53 +0100 Subject: 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 --- src/globals.c | 45 ++++++++++++++++++++++-------- 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; } -- cgit v1.2.3