From 5b1175ae8b46fc6c8b74cbde24e26204b6589f50 Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Wed, 10 Feb 2021 17:19:31 +0000 Subject: [PATCH] JAL-3251 On linux set (sun.awt.X11.XToolkit.)awtAppClassName to set the grouped application name in the taskbar --- src/jalview/gui/Desktop.java | 59 +++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index abe1fad..195a313 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -54,8 +54,10 @@ import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.lang.reflect.Field; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; import java.util.List; @@ -394,24 +396,61 @@ public class Desktop extends jalview.jbgui.GDesktop doConfigureStructurePrefs(); setTitle(ChannelProperties.getProperty("app_name") + " " + Cache.getProperty("VERSION")); - /* - if (!Platform.isAMac()) - { - // this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - } - else + + /** + * Set taskbar "grouped windows" name for linux desktops (works in GNOME and KDE). + * This uses sun.awt.X11.XToolkit.awtAppClassName which is not officially documented or + * guaranteed to exist, so we access it via reflection. + * There appear to be unfathomable criteria about what this string can contain, and it if doesn't + * meet those criteria then "java" (KDE) or "jalview-bin-Jalview" (GNOME) is used. + * "Jalview", "Jalview Develop" and "Jalview Test" seem okay, but "Jalview non-release" does not. + * The reflection access may generate a warning: + * WARNING: An illegal reflective access operation has occurred + * WARNING: Illegal reflective access by jalview.gui.Desktop () to field sun.awt.X11.XToolkit.awtAppClassName + * which I don't think can be avoided. + */ + if (Platform.isLinux()) { - this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + try + { + Toolkit xToolkit = Toolkit.getDefaultToolkit(); + Field[] declaredFields = xToolkit.getClass().getDeclaredFields(); + Field awtAppClassNameField = null; + + if (Arrays.stream(declaredFields).anyMatch(f -> f.getName().equals("awtAppClassName"))) + { + awtAppClassNameField = xToolkit.getClass() + .getDeclaredField("awtAppClassName"); + } + + String title = ChannelProperties.getProperty("app_name"); + if (awtAppClassNameField != null) + { + awtAppClassNameField.setAccessible(true); + awtAppClassNameField.set(xToolkit, title); + } + else + { + Cache.log.debug("XToolkit: awtAppClassName not found"); + } + } catch (Exception e) + { + Cache.debug("Error setting awtAppClassName"); + Cache.trace(Cache.getStackTraceString(e)); + } } - */ + /** + * APQHandlers sets handlers for About, Preferences and Quit actions peculiar to macOS's application menu. + * APQHandlers will check to see if a handler is supported before setting it. + */ try { APQHandlers.setAPQHandlers(this); } catch (Throwable t) { - System.out.println("Error setting APQHandlers: " + t.toString()); - // t.printStackTrace(); + Cache.warn("Error setting APQHandlers: " + t.toString()); + Cache.trace(Cache.getStackTraceString(t)); } setIconImages(ChannelProperties.getIconList()); -- 1.7.10.2