Home > Software engineering >  Why is WM_NAME atom not set for certain locales
Why is WM_NAME atom not set for certain locales

Time:09-23

I recently discovered that the X11 atom WM_NAME is not set in Swing JFrame when LANG is set to C.utf8 but is set for other values of LANG. This occurs on Linux Redhat 8.2 with OpenJDK 11.0.9.

Result with xprop | grep -i name when LANG=C.utf8

_NET_WM_ICON_NAME(UTF8_STRING) = "title 123"
_NET_WM_NAME(UTF8_STRING) = "title 123"

Result with xprop | grep -i name when LANG=en_GB.UTF-8

_NET_WM_ICON_NAME(UTF8_STRING) = "title 123"
WM_ICON_NAME(STRING) = "title 123"
_NET_WM_NAME(UTF8_STRING) = "title 123"
WM_NAME(STRING) = "title 123

Simple JFrame with title used

public class Example {
    public static void main(String[] args) {
        new javax.swing.JFrame("title 123").setVisible(true);
    }
}

I've traced this through to sun.awt.X11.XBaseWindow.updateWMName() which updates both VM_NAME and _NET_WM_NAME unconditionally

XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME);
nameAtom.setProperty(getWindow(), name);
XAtom netNameAtom = XAtom.get("_NET_WM_NAME");
netNameAtom.setPropertyUTF8(getWindow(), name);

So I'm guessing that somewhere lower in X11 libraries the atom is either not being set or being rejected, possibly to do with character encoding.

I do understand that WM_NAME is legacy and optional and _NET_WM_NAME is the modern replacement. The reason this matters to me is that I maintain some legacy bespoke window manager style code that only looks for WM_NAME. I will be shortly enhancing this to look for _NET_WM_NAME too. I just want to understand this fully for my own academic geeky interest

CodePudding user response:

Tracing further sun.awt.X11.XAtom.setProperty(long, String) calls out to native method sun.awt.X11.XlibWrapper.SetProperty(long, long, long, String)

This is implemented by https://github.com/openjdk/jdk/blob/master/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c

#ifdef X_HAVE_UTF8_STRING
    status = Xutf8TextListToTextProperty((Display *)jlong_to_ptr(display), &cname, 1,
                                   XStdICCTextStyle, &tp);
#else
    status = XmbTextListToTextProperty((Display *)jlong_to_ptr(display), &cname, 1,
                                   XStdICCTextStyle, &tp);
#endif

if (status == Success || status > 0) {
    XChangeProperty((Display *)jlong_to_ptr(display), window, atom, tp.encoding, tp.format, PropModeReplace, tp.value, tp.nitems);
    if (tp.value != NULL) {
        XFree(tp.value);
    }
}

This implies that if Xutf8TextListToTextProperty is unsuccessful then no error is reported.

Xutf8TextListToTextProperty is provided by Xutils.h which comes from https://gitlab.freedesktop.org/xorg/lib/libx11

It appears that libX11 has its own i18n implementation and until libX11 1.7.1 it did not "understand" LANG=C.utf8, although it did have an alias for C.UTF-8, this was corrected by commit https://github.com/mirror/libX11/commit/cc9f8878f2cbe17c7b4035b4ff4352b52ece38e0 which added an alias to /usr/share/X11/locale/locale.alias

C.utf8:                     en_US.UTF-8

The commit message answers the question concisely

The normal form is 'C.UTF-8', but 'C.utf8' has been seen in the wild.

If I manually change /usr/share/X11/locale/locale.alias and run my example with LANG=C.utf8 then WM_NAME and other atoms are set correctly.

  • Related