为何在特定Locale(C.utf8)下Swing JFrame的WM_NAME原子未被设置?
最近在Red Hat 8.2 + OpenJDK 11.0.9的环境下折腾Swing程序时,发现了一个奇怪的X11行为:当系统LANG环境变量设为C.utf8时,JFrame对应的X11原子WM_NAME居然没被设置;但把LANG换成en_GB.UTF-8这类其他UTF-8 locale时,WM_NAME就会正常出现。
测试结果对比
当LANG=C.utf8时
执行xprop | grep -i name的输出只有现代标准的窗口名称原子:
_NET_WM_ICON_NAME(UTF8_STRING) = "title 123" _NET_WM_NAME(UTF8_STRING) = "title 123"
当LANG=en_GB.UTF-8时
输出同时包含遗留的WM_NAME和WM_ICON_NAME:
_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"
复现用的极简代码
我用最基础的JFrame代码就能复现这个问题:
public class Example { public static void main(String[] args) { new javax.swing.JFrame("title 123").setVisible(true); } }
跟进OpenJDK底层代码后的发现
我追踪到OpenJDK里负责设置窗口名称的逻辑在sun.awt.X11.XBaseWindow.updateWMName()方法,这段代码看起来是同时处理WM_NAME和_NET_WM_NAME的,没有条件分支:
XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME); nameAtom.setProperty(getWindow(), name); XAtom netNameAtom = XAtom.get("_NET_WM_NAME"); netNameAtom.setPropertyUTF8(getWindow(), name);
我的猜测
既然上层Java代码是无条件设置WM_NAME的,那问题应该出在X11底层库的调用环节。推测是当LANG=C.utf8时,底层对WM_NAME这个遗留原子的字符编码处理出了问题,导致设置请求被拒绝或者静默失败。
我清楚WM_NAME是X11的遗留可选原子,_NET_WM_NAME才是现代窗口管理器的标准方案——后续我会把维护的遗留定制窗口管理器升级成同时支持_NET_WM_NAME,但出于技术好奇心,还是希望能彻底搞明白这个现象的根因。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

