Janek Kozicki <[EMAIL PROTECTED]> writes: > thanks, but I was unable to test your patch. I tried it against > 1.3, 1.3.1 and svn-HEAD - I was unable to resolve conflicts by hand.
Yes, it was a patch against a previous patch. Things get complicated without version control. Attached is a diff against 1.3.2. The patch series is available at http://www.iki.fi/tkorvola/sawfish.git, branch utf-8-names-fix. I may post it to the wiki if I find the time. To illustrate the difference, run Sawfish in a non-UTF-8 locale but with a title font capable of displaying Unicode (I use Freemono), start a uxterm and gucharmap, then try xterm -T 'funny characters' and konsole -T 'funny characters', where the funny characters are not representable in the locale of Sawfish. With the Net_wm_names patch, only konsole gets its title rendered correctly but xterm does not. With the attached patch, both windows get correct titles. The issues raised here remain unaddressed though: <URL:http://mail.gnome.org/archives/sawfish-list/2007-October/msg00018.html>. -- Timo Korvola <URL:http://www.iki.fi/tkorvola> diff --git a/src/events.c b/src/events.c index 4b58c7c..364be1c 100644 --- a/src/events.c +++ b/src/events.c @@ -479,106 +479,110 @@ motion_notify (XEvent *ev) static bool update_window_name(Lisp_Window * w, XPropertyEvent xproperty) { - u_char *prop; - Atom actual; - int format; - long nitems, bytes_after; - char **text_list; - XTextProperty tprop; - int count; - repv str = Qnil; - int convert_status; - - if (xproperty.state != PropertyNewValue - || XGetWindowProperty (dpy, w->id, xproperty.atom, - 0, 200, False, AnyPropertyType, &actual, - &format, &nitems, - &bytes_after, &prop) != Success - || actual == None) - return FALSE; - - if (format != 8 || WINDOW_IS_GONE_P (w)) - return FALSE; - - tprop.value = prop; - tprop.encoding = actual; - tprop.format = format; - tprop.nitems = strlen (prop); - - if (actual == xa_compound_text || actual == XA_STRING) + u_char *prop; + Atom actual; + int format; + long nitems, bytes_after; + char **text_list; + XTextProperty tprop; + int count; + repv str = Qnil; + int convert_status; + + if (xproperty.state != PropertyNewValue + || XGetWindowProperty (dpy, w->id, xproperty.atom, + 0, 200, False, AnyPropertyType, &actual, + &format, &nitems, + &bytes_after, &prop) != Success + || actual == None) + return FALSE; + + if (format != 8 || WINDOW_IS_GONE_P (w)) { - convert_status = XmbTextPropertyToTextList (dpy, &tprop, &text_list, &count); - if (convert_status >= Success && count > 0) - { - char * utf8str = g_locale_to_utf8(text_list[0], -1, NULL, NULL, NULL); - if (utf8str) - str = rep_string_dup (utf8str); - } - XFreeStringList(text_list); + XFree (prop); + return FALSE; } + tprop.value = prop; + tprop.encoding = actual; + tprop.format = format; + tprop.nitems = strlen (prop); + #ifdef X_HAVE_UTF8_STRING - if (actual == xa_utf8_string) + if (actual == xa_compound_text || actual == XA_STRING + || actual == xa_utf8_string) + { + convert_status = Xutf8TextPropertyToTextList (dpy, &tprop, &text_list, + &count); + if (convert_status >= Success && count > 0) + str = rep_string_dup (text_list[0]); + XFreeStringList(text_list); + } +#else + if (actual == xa_compound_text || actual == XA_STRING) { - convert_status = Xutf8TextPropertyToTextList (dpy, &tprop, &text_list, &count); - if (convert_status >= Success && count > 0) - str = rep_string_dup (text_list[0]); - XFreeStringList(text_list); + convert_status = XmbTextPropertyToTextList (dpy, &tprop, &text_list, + &count); + if (convert_status >= Success) + { + if (count > 0) + { + char * utf8str = g_locale_to_utf8(text_list[0], -1, + NULL, NULL, NULL); + if (utf8str) + { + str = rep_string_dup (utf8str); + g_free (utf8str); + } + } + XFreeStringList(text_list); + } } #endif - XFree (prop); + XFree (prop); - if (str == Qnil) - return FALSE; + if (str == Qnil) + return FALSE; - if (xproperty.atom == xa_wm_net_name) + if (xproperty.atom == xa_wm_net_name + && str != Qnil && Fequal (w->net_name, str) == Qnil) { - if ( str != Qnil && Fequal (w->net_name, str) == Qnil) - { - w->net_name = str; - return TRUE; - } + w->net_name = str; + return TRUE; } - if (xproperty.atom == xa_wm_net_icon_name) + if (xproperty.atom == xa_wm_net_icon_name + && str != Qnil && Fequal (w->net_icon_name, str) == Qnil) { - if ( str != Qnil && Fequal (w->net_icon_name, str) == Qnil) - { - w->net_icon_name = str; - return TRUE; - } + w->net_icon_name = str; + return TRUE; } - /* No point in updating the rest if we have the _NET ones. They won't - be used anyways. */ - if (w->net_name != Qnil) - return FALSE; - - if (xproperty.atom == XA_WM_NAME) + if (w->net_name == Qnil && xproperty.atom == XA_WM_NAME) { - if (str == Qnil) - str = rep_null_string (); - if (Fequal (w->name, str) == Qnil - || Fequal (w->full_name, str) == Qnil) - { - w->full_name = w->name = str; - return TRUE; - } + if (str == Qnil) + str = rep_null_string (); + if (Fequal (w->name, str) == Qnil + || Fequal (w->full_name, str) == Qnil) + { + w->full_name = w->name = str; + return TRUE; + } } - if (xproperty.atom == XA_WM_ICON_NAME) + if (w->net_icon_name == Qnil && xproperty.atom == XA_WM_ICON_NAME) { - if (str == Qnil) - str = rep_null_string (); - if (Fequal (w->icon_name, str) == Qnil) - { - w->icon_name = str; - return TRUE; - } - } + if (str == Qnil) + str = rep_null_string (); + if (Fequal (w->icon_name, str) == Qnil) + { + w->icon_name = str; + return TRUE; + } + } - return FALSE; + return FALSE; } static void @@ -614,16 +618,15 @@ property_notify (XEvent *ev) break; default: - - if (ev->xproperty.atom == XA_WM_NAME || - ev->xproperty.atom == XA_WM_ICON_NAME || - ev->xproperty.atom == xa_wm_net_name || - ev->xproperty.atom == xa_wm_net_icon_name ) - { - need_refresh = changed = - update_window_name(w, ev->xproperty); - } - else if (ev->xproperty.atom == xa_wm_colormap_windows) + if (ev->xproperty.atom == XA_WM_NAME || + ev->xproperty.atom == XA_WM_ICON_NAME || + ev->xproperty.atom == xa_wm_net_name || + ev->xproperty.atom == xa_wm_net_icon_name ) + { + need_refresh = changed = + update_window_name(w, ev->xproperty); + } + else if (ev->xproperty.atom == xa_wm_colormap_windows) { if (w->n_cmap_windows > 0) XFree (w->cmap_windows); diff --git a/src/windows.c b/src/windows.c index 734032c..b7e2da6 100644 --- a/src/windows.c +++ b/src/windows.c @@ -356,85 +356,73 @@ remove_window_frame (Lisp_Window *w) } } + +static repv +text_prop_to_utf8 (XTextProperty *prop) +{ + repv rval = Qnil; + if (prop->value && prop->nitems > 0) + { + char **list; + int count; + prop->nitems = strlen(prop->value); +#ifdef X_HAVE_UTF8_STRING + if (Xutf8TextPropertyToTextList (dpy, prop, &list, &count) >= Success) + { + if (count > 0) + rval = rep_string_dup (list[0]); + XFreeStringList (list); + } +#else + if (XmbTextPropertyToTextList (dpy, prop, &list, &count) >= Success) + { + if (count > 0) { + gchar *ustr = g_locale_to_utf8(list[0], -1, NULL, NULL, NULL); + if (ustr) + { + rval = rep_string_dup (ustr); + g_free (ustr); + } + } + XFreeStringList (list); + } +#endif + } + return rval; +} + + /* Queries X properties to get the window {icon,}name */ static void -get_window_name(Lisp_Window * w) +get_window_name(Lisp_Window *w) { - char *tem; - XTextProperty prop; + XTextProperty prop; - /* We only try to use the utf8 properties if our xlib supports them */ + /* We only try to use the utf8 properties if our xlib supports them. + Otherwise conversion would have to go via the current locale, which + might lose some characters. */ #ifdef X_HAVE_UTF8_STRING - if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_name) && prop.value) { - if (prop.nitems > 0) - { - char **list; - int count; - prop.nitems = strlen(prop.value); - if (Xutf8TextPropertyToTextList (dpy, &prop, &list, &count) - >= Success) - { - if (count > 0) - w->net_name = rep_string_dup (list[0]); - XFreeStringList (list); - } - } - } - - if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_icon_name) && prop.value) { - if (prop.nitems > 0) - { - char **list; - int count; - prop.nitems = strlen(prop.value); - if (Xutf8TextPropertyToTextList (dpy, &prop, &list, &count) - >= Success) - { - if (count > 0) - w->net_icon_name = rep_string_dup (list[0]); - XFreeStringList (list); - } - } - } - - /* If we got the _NET names, there's no point in querying the others, - as they won't be used anyways. */ - if (w->net_name != Qnil) - return; - + if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_name)) + w->net_name = text_prop_to_utf8 (&prop); + if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_icon_name)) + w->net_icon_name = text_prop_to_utf8 (&prop); #endif - if (XGetWMName (dpy, w->id, &prop) && prop.value) + if (w->net_name == Qnil && XGetWMName (dpy, w->id, &prop)) { - if (prop.nitems > 0) - { - char **list; - int count; - prop.nitems = strlen(prop.value); - if (XmbTextPropertyToTextList (dpy, &prop, &list, &count) - >= Success) - { - if (count > 0) - w->name = rep_string_dup (g_locale_to_utf8(list[0], - -1, NULL, NULL, NULL)); - XFreeStringList (list); - } - } - XFree (prop.value); + repv name = text_prop_to_utf8 (&prop); + if (name != Qnil) + w->name = name; } - w->full_name = w->name; + w->full_name = w->name; - if (XGetIconName (dpy, w->id, &tem)) - { - w->icon_name = rep_string_dup (g_locale_to_utf8(tem, - -1, NULL, NULL, NULL)); - XFree (tem); - } - else - w->icon_name = w->name; - + if (w->net_icon_name == Qnil && XGetWMIconName (dpy, w->id, &prop)) + w->icon_name = text_prop_to_utf8 (&prop); + if (w->icon_name == Qnil) + w->icon_name = w->name; } + /* Add the top-level window ID to the manager's data structures */ Lisp_Window * add_window (Window id)
