diff --git a/src/dorkbox/systemTray/MenuItem.java b/src/dorkbox/systemTray/MenuItem.java index 48f4edf..a0bc7be 100644 --- a/src/dorkbox/systemTray/MenuItem.java +++ b/src/dorkbox/systemTray/MenuItem.java @@ -24,7 +24,7 @@ import java.net.URL; import javax.imageio.stream.ImageInputStream; import dorkbox.systemTray.peer.MenuItemPeer; -import dorkbox.systemTray.util.ImageUtils; +import dorkbox.systemTray.util.ImageResizeUtil; import dorkbox.util.SwingUtil; /** @@ -83,32 +83,32 @@ class MenuItem extends Entry { public MenuItem(final String text, final String imagePath, final ActionListener callback) { - this(text, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imagePath), callback, false); + this(text, ImageResizeUtil.shouldResizeOrCache(false, imagePath), callback, false); } public MenuItem(final String text, final File imageFile, final ActionListener callback) { - this(text, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageFile), callback, false); + this(text, ImageResizeUtil.shouldResizeOrCache(false, imageFile), callback, false); } public MenuItem(final String text, final URL imageUrl, final ActionListener callback) { - this(text, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl), callback, false); + this(text, ImageResizeUtil.shouldResizeOrCache(false, imageUrl), callback, false); } public MenuItem(final String text, final InputStream imageStream, final ActionListener callback) { - this(text, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageStream), callback, false); + this(text, ImageResizeUtil.shouldResizeOrCache(false, imageStream), callback, false); } public MenuItem(final String text, final Image image, final ActionListener callback) { - this(text, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, image), callback, false); + this(text, ImageResizeUtil.shouldResizeOrCache(false, image), callback, false); } public MenuItem(final String text, final ImageInputStream imageStream, final ActionListener callback) { - this(text, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageStream), callback, false); + this(text, ImageResizeUtil.shouldResizeOrCache(false, imageStream), callback, false); } // the last parameter (unused) is there so the signature is different @@ -213,7 +213,7 @@ class MenuItem extends Entry { */ public void setImage(final File imageFile) { - setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageFile)); + setImage_(ImageResizeUtil.shouldResizeOrCache(false, imageFile)); } /** @@ -225,7 +225,7 @@ class MenuItem extends Entry { */ public void setImage(final String imagePath) { - setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imagePath)); + setImage_(ImageResizeUtil.shouldResizeOrCache(false, imagePath)); } /** @@ -237,7 +237,7 @@ class MenuItem extends Entry { */ public void setImage(final URL imageUrl) { - setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl)); + setImage_(ImageResizeUtil.shouldResizeOrCache(false, imageUrl)); } /** @@ -249,7 +249,7 @@ class MenuItem extends Entry { */ public void setImage(final InputStream imageStream) { - setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageStream)); + setImage_(ImageResizeUtil.shouldResizeOrCache(false, imageStream)); } /** @@ -261,7 +261,7 @@ class MenuItem extends Entry { */ public void setImage(final Image image) { - setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, image)); + setImage_(ImageResizeUtil.shouldResizeOrCache(false, image)); } /** @@ -273,7 +273,7 @@ class MenuItem extends Entry { */ public void setImage(final ImageInputStream imageStream) { - setImage_(ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageStream)); + setImage_(ImageResizeUtil.shouldResizeOrCache(false, imageStream)); } diff --git a/src/dorkbox/systemTray/SystemTray.java b/src/dorkbox/systemTray/SystemTray.java index d2fa54f..12218f0 100644 --- a/src/dorkbox/systemTray/SystemTray.java +++ b/src/dorkbox/systemTray/SystemTray.java @@ -20,11 +20,9 @@ import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileReader; import java.io.InputStream; -import java.io.PrintStream; import java.net.URL; import java.util.concurrent.atomic.AtomicReference; @@ -35,10 +33,13 @@ import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JSeparator; import javax.swing.SwingUtilities; +import javax.swing.UIManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.sun.java.swing.plaf.gtk.GTKLookAndFeel; + import dorkbox.systemTray.jna.linux.AppIndicator; import dorkbox.systemTray.jna.linux.Gtk; import dorkbox.systemTray.nativeUI.NativeUI; @@ -47,8 +48,8 @@ import dorkbox.systemTray.nativeUI._AwtTray; import dorkbox.systemTray.nativeUI._GtkStatusIconNativeTray; import dorkbox.systemTray.swingUI.SwingUIFactory; import dorkbox.systemTray.swingUI._SwingTray; -import dorkbox.systemTray.util.ImageUtils; import dorkbox.systemTray.util.JavaFX; +import dorkbox.systemTray.util.SizeAndScalingUtil; import dorkbox.systemTray.util.Swt; import dorkbox.systemTray.util.SystemTrayFixes; import dorkbox.util.CacheUtil; @@ -57,15 +58,15 @@ import dorkbox.util.OS; import dorkbox.util.OSUtil; import dorkbox.util.Property; import dorkbox.util.SwingUtil; -import dorkbox.util.process.ShellProcessBuilder; +import sun.security.action.GetPropertyAction; /** - * Professional, cross-platform **SystemTray**, **AWT**, **GtkStatusIcon**, and **AppIndicator** support for java applications. + * Professional, cross-platform **SystemTray**, **AWT**, **GtkStatusIcon**, and **AppIndicator** support for Java applications. *
* This library provides **OS native** menus and **Swing** menus. *
- * Auto-detection will use DEFAULT_TRAY_SIZE or DEFAULT_MENU_SIZE as a 'base-line' for determining what size to use. + * Auto-detection will use DEFAULT_TRAY_SIZE as a 'base-line' for determining what size to use. *
* If auto-detection fails and the incorrect size is detected or used, disable this and specify the correct DEFAULT_TRAY_SIZE or * DEFAULT_MENU_SIZE instead */ - public static boolean AUTO_TRAY_SIZE = true; - - @Property - /** - * Size of the tray, so that the icon can be properly scaled based on OS. - *
- * This value can be automatically scaled based on the the platform and scaling-factor. - * - Windows will automatically scale up/down. - * - GtkStatusIcon will usually automatically scale up/down - * - AppIndicators will not always automatically scale (it will sometimes display whatever is specified here) - *
- * You will experience WEIRD graphical glitches if this is NOT a power of 2. - */ - public static int DEFAULT_TRAY_SIZE = 16; - - @Property - /** - * Size of the menu entries, so that the icon can be properly scaled based on OS. - *
- * You will experience WEIRD graphical glitches if this is NOT a power of 2. - */ - public static int DEFAULT_MENU_SIZE = 16; + public static boolean AUTO_SIZE = true; @Property /** Forces the system tray to always choose GTK2 (even when GTK3 might be available). */ @@ -128,7 +108,7 @@ class SystemTray { *
* This is an advanced feature, and it is recommended to leave at AutoDetect.
*/
- public static TrayType FORCE_TRAY_TYPE = TrayType.AutoDetect;
+ public static TrayType FORCE_TRAY_TYPE = TrayType.Swing;
@Property
/**
@@ -149,7 +129,7 @@ class SystemTray {
@Property
/**
- * Allows the developer to provide a custom look and feel for the Swing UI, if defined. See the test example for specific use.
+ * Allows a custom look and feel for the Swing UI, if defined. See the test example for specific use.
*/
public static SwingUIFactory SWING_UI = null;
@@ -157,7 +137,7 @@ class SystemTray {
/**
* This property is provided for debugging any errors in the logic used to determine the system-tray type.
*/
- public static boolean DEBUG = false;
+ public static boolean DEBUG = true;
private static volatile SystemTray systemTray = null;
@@ -201,6 +181,7 @@ class SystemTray {
case Swing: return tray == _SwingTray.class;
case AWT: return tray == _AwtTray.class;
}
+
return false;
}
@@ -301,8 +282,47 @@ class SystemTray {
}
}
else if (OS.isLinux() || OS.isUnix()) {
- // kablooie if SWT/JavaFX is not configured in a way that works with us.
+ // kablooie if SWT/JavaFX or Swing is not configured in a way that works with us.
if (FORCE_TRAY_TYPE != TrayType.Swing) {
+ // NOTE: if the UI uses the 'getSystemLookAndFeelClassName' and is on Linux, this will cause GTK2 to get loaded first,
+ // which will cause conflicts if one tries to use GTK3
+ if (!FORCE_GTK2 && !isJavaFxLoaded && !isSwtLoaded) {
+
+ String currentUI = UIManager.getLookAndFeel()
+ .getClass()
+ .getName();
+
+ boolean mustForceGtk2 = false;
+
+ if (currentUI.equals(GTKLookAndFeel.class.getCanonicalName())) {
+ // this means our look and feel is the GTK look and feel... THIS CREATES PROBLEMS!
+
+ // THIS IS NOT DOCUMENTED ANYWHERE...
+ String swingGtkVersion = java.security.AccessController.doPrivileged(new GetPropertyAction("swing.gtk.version"));
+ mustForceGtk2 = swingGtkVersion == null || swingGtkVersion.startsWith("2");
+ }
+
+ if (mustForceGtk2) {
+ // we are NOT using javaFX/SWT and our UI is GTK2 and we want GTK3
+ // JavaFX/SWT can be GTK3, but Swing can not be GTK3.
+
+ if (AUTO_FIX_INCONSISTENCIES) {
+ // we must use GTK2 because Swing is configured to use GTK2
+ logger.warn("Forcing GTK2 because the Swing UIManager is GTK2");
+ FORCE_GTK2 = true;
+ } else {
+ logger.error("Unable to use the SystemTray when the Swing UIManager is configured to use the native L&F, which " +
+ "uses GTK2. This is incompatible with GTK3. " +
+ "Please set `SystemTray.AUTO_FIX_INCONSISTENCIES=true;` to automatically fix this problem.");
+
+ systemTrayMenu = null;
+ systemTray = null;
+ return;
+ }
+ }
+ }
+
+
if (isSwtLoaded) {
// Necessary for us to work with SWT based on version info. We can try to set us to be compatible with whatever it is set to
// System.setProperty("SWT_GTK3", "0");
@@ -336,8 +356,8 @@ class SystemTray {
// http://mail.openjdk.java.net/pipermail/openjfx-dev/2016-May/019100.html
// https://docs.oracle.com/javafx/2/system_requirements_2-2-3/jfxpub-system_requirements_2-2-3.htm
// from the page: JavaFX 2.2.3 for Linux requires gtk2 2.18+.
- boolean isJFX_GTK3 = System.getProperty("jdk.gtk.version", "2").equals("3");
- if (isJFX_GTK3 && FORCE_GTK2) {
+ boolean isJava_GTK3_Possible = OS.javaVersion >= 9 && System.getProperty("jdk.gtk.version", "2").equals("3");
+ if (isJava_GTK3_Possible && FORCE_GTK2) {
// if we are java9, then we can change it -- otherwise we cannot.
if (OS.javaVersion == 9 && AUTO_FIX_INCONSISTENCIES) {
logger.warn("Unable to use the SystemTray when JavaFX is configured to use GTK3 and the SystemTray is " +
@@ -353,7 +373,7 @@ class SystemTray {
systemTray = null;
return;
}
- } else if (!isJFX_GTK3 && !FORCE_GTK2 && AUTO_FIX_INCONSISTENCIES) {
+ } else if (!isJava_GTK3_Possible && !FORCE_GTK2 && AUTO_FIX_INCONSISTENCIES) {
// we must use GTK2, because JavaFX is GTK2
logger.warn("Forcing GTK2 because JavaFX is GTK2");
FORCE_GTK2 = true;
@@ -374,10 +394,15 @@ class SystemTray {
logger.debug("{} {} {}", jvmVendor, jvmName, jvmVersion);
- logger.debug("Is AutoTraySize? {}", AUTO_TRAY_SIZE);
+ logger.debug("Is Auto sizing tray/menu? {}", AUTO_SIZE);
logger.debug("Is JavaFX detected? {}", isJavaFxLoaded);
logger.debug("Is SWT detected? {}", isSwtLoaded);
- logger.debug("Forced tray type: {}", FORCE_TRAY_TYPE.name());
+ if (FORCE_TRAY_TYPE == TrayType.AutoDetect) {
+ logger.debug("Auto-detecting tray type");
+ }
+ else {
+ logger.debug("Forced tray type: {}", FORCE_TRAY_TYPE.name());
+ }
logger.debug("FORCE_GTK2: {}", FORCE_GTK2);
}
@@ -388,9 +413,6 @@ class SystemTray {
// this has to happen BEFORE any sort of swing system tray stuff is accessed
if (OS.isWindows()) {
- // windows is funky, and is hardcoded to 16x16. We fix that.
- SystemTrayFixes.fixWindows();
-
try {
trayType = selectType(TrayType.Swing);
} catch (Throwable e) {
@@ -421,9 +443,10 @@ class SystemTray {
if (SystemTray.FORCE_TRAY_TYPE == TrayType.Swing && isSwtLoaded) {
if (AUTO_FIX_INCONSISTENCIES) {
- logger.warn("Forcing AWT because SWT cannot load Swing type.");
+ logger.warn("Forcing AWT because SWT cannot load Swing tray type.");
trayType = selectTypeQuietly(TrayType.AWT);
- } else {
+ }
+ else {
logger.error("Cannot initialize Swing type if SWT is loaded.");
systemTrayMenu = null;
@@ -432,123 +455,129 @@ class SystemTray {
}
}
+ // Ubuntu UNITY has issues with GtkStatusIcon (it won't work...)
+ if (isTrayType(trayType, TrayType.GtkStatusIcon) && OSUtil.DesktopEnv.get() == OSUtil.DesktopEnv.Env.Unity && OSUtil.Linux.isUbuntu()) {
+ if (AUTO_FIX_INCONSISTENCIES) {
+ // we must use AppIndicator because Ubuntu Unity removed GtkStatusIcon support
+ logger.warn("Forcing AppIndicator because Ubuntu Unity display environment removed support for GtkStatusIcons.");
+ SystemTray.FORCE_TRAY_TYPE = TrayType.AppIndicator; // this is required because of checks inside of AppIndicator...
+ trayType = selectTypeQuietly(TrayType.AppIndicator);
+ }
+ else {
+ logger.error("Unable to use the GtkStatusIcons when running on Ubuntu with the Unity display environment, and thus" +
+ " the SystemTray will not work. " +
+ "Please set `SystemTray.AUTO_FIX_INCONSISTENCIES=true;` to automatically fix this problem.");
+
+ systemTrayMenu = null;
+ systemTray = null;
+ return;
+ }
+ }
// quick check, because we know that unity uses app-indicator. Maybe REALLY old versions do not. We support 14.04 LTE at least
-
- // if we are running as ROOT, we *** WILL NOT *** have access to 'XDG_CURRENT_DESKTOP'
- // *unless env's are preserved, but they are not guaranteed to be
- // see: http://askubuntu.com/questions/72549/how-to-determine-which-window-manager-is-running
- String XDG = System.getenv("XDG_CURRENT_DESKTOP");
- if (XDG == null) {
- // maybe we are running as root???
- XDG = "unknown"; // try to autodetect if we should use app indicator or gtkstatusicon
- }
-
-
- // BLEH. if gnome-shell is running, IT'S REALLY GNOME!
- // we must ALWAYS do this check!!
- boolean isReallyGnome = OSUtil.DesktopEnv.isGnome();
-
- if (isReallyGnome) {
- if (DEBUG) {
- logger.error("Auto-detected that gnome-shell is running");
- }
- XDG = "gnome";
- }
-
- if (DEBUG) {
- logger.debug("Currently using the '{}' desktop", XDG);
- }
-
if (trayType == null) {
- // Unity is a weird combination. It's "Gnome", but it's not "Gnome Shell".
- if ("unity".equalsIgnoreCase(XDG)) {
- trayType = selectTypeQuietly(TrayType.AppIndicator);
+ OSUtil.DesktopEnv.Env de = OSUtil.DesktopEnv.get();
+
+ if (DEBUG) {
+ logger.debug("Currently using the '{}' desktop environment", de);
}
- else if ("xfce".equalsIgnoreCase(XDG)) {
- // NOTE: XFCE used to use appindicator3, which DOES NOT support images in the menu. This change was reverted.
- // see: https://ask.fedoraproject.org/en/question/23116/how-to-fix-missing-icons-in-program-menus-and-context-menus/
- // see: https://git.gnome.org/browse/gtk+/commit/?id=627a03683f5f41efbfc86cc0f10e1b7c11e9bb25
- // so far, it is OK to use GtkStatusIcon on XFCE <-> XFCE4 inclusive
- trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
- }
- else if ("lxde".equalsIgnoreCase(XDG)) {
- trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
- }
- else if ("kde".equalsIgnoreCase(XDG)) {
- if (OSUtil.Linux.isFedora()) {
- // Fedora KDE requires GtkStatusIcon
- trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
- } else {
- // kde (at least, plasma 5.5.6) requires appindicator
- trayType = selectTypeQuietly(TrayType.AppIndicator);
- }
+ switch (de) {
+ case Gnome: {
+ // check other DE / OS combos that are based on gnome
+ String GDM = System.getenv("GDMSESSION");
- // kde 5.8+ is "high DPI", so we need to adjust the scale. Image resize will do that
- }
- else if ("pantheon".equalsIgnoreCase(XDG)) {
- // elementaryOS. It only supports appindicator (not gtkstatusicon)
- // http://bazaar.launchpad.net/~wingpanel-devs/wingpanel/trunk/view/head:/sample/SampleIndicator.vala
+ if (DEBUG) {
+ logger.debug("Currently using the '{}' session type", GDM);
+ }
- // ElementaryOS shows the checkbox on the right, everyone else is on the left.
- // With eOS, we CANNOT show the spacer image. It does not work.
- trayType = selectTypeQuietly(TrayType.AppIndicator);
- }
- else if ("gnome".equalsIgnoreCase(XDG)) {
- // check other DE
- String GDM = System.getenv("GDMSESSION");
+ if ("gnome".equalsIgnoreCase(GDM)) {
+ Tray.usingGnome = true;
- if (DEBUG) {
- logger.debug("Currently using the '{}' session type", GDM);
- }
+ // are we fedora? If so, what version?
+ // now, what VERSION of fedora? 23/24/25/? don't have AppIndicator installed, so we have to use GtkStatusIcon
+ if (OSUtil.Linux.isFedora()) {
+ if (DEBUG) {
+ logger.debug("Running Fedora");
+ }
- if ("gnome".equalsIgnoreCase(GDM)) {
- Tray.usingGnome = true;
+ // 23 is gtk, 24/25 is gtk (but also wrong size unless we adjust it. ImageUtil automatically does this)
+ trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ }
+ else if (OSUtil.Linux.isUbuntu()) {
+ // so far, because of the interaction between gnome3 + ubuntu, the GtkStatusIcon miraculously works.
+ trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ }
+ else if (OSUtil.Unix.isFreeBSD()) {
+ trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ }
+ else {
+ // arch likely will have problems unless the correct/appropriate libraries are installed.
+ trayType = selectTypeQuietly(TrayType.AppIndicator);
+ }
+ }
+ else if ("cinnamon".equalsIgnoreCase(GDM)) {
+ trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ }
+ else if ("default".equalsIgnoreCase(GDM)) {
+ // this can be gnome3 on debian
- // are we fedora? If so, what version?
- // now, what VERSION of fedora? 23/24/25/? don't have AppIndicator installed, so we have to use GtkStatusIcon
- if (OSUtil.Linux.isFedora()) {
- if (DEBUG) {
- logger.debug("Running Fedora");
+ if (OSUtil.Linux.isDebian()) {
+ // note: Debian Gnome3 does NOT work! (tested on Debian 8.5 and 8.6 default installs)
+ logger.warn("Debian with Gnome detected. SystemTray support is not known to work.");
}
- // 23 is gtk, 24/25 is gtk (but also wrong size unless we adjust it. ImageUtil automatically does this)
trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
}
- else if (OSUtil.Linux.isUbuntu()) {
- // so far, because of the interaction between gnome3 + ubuntu, the GtkStatusIcon miraculously works.
+ else if ("gnome-classic".equalsIgnoreCase(GDM)) {
trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
}
- else if (OSUtil.Unix.isFreeBSD()) {
+ else if ("gnome-fallback".equalsIgnoreCase(GDM)) {
trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
}
- else {
- // arch likely will have problems unless the correct/appropriate libraries are installed.
+ else if ("ubuntu".equalsIgnoreCase(GDM)) {
trayType = selectTypeQuietly(TrayType.AppIndicator);
}
+ break;
}
- else if ("cinnamon".equalsIgnoreCase(GDM)) {
- trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
- }
- else if ("default".equalsIgnoreCase(GDM)) {
- // this can be gnome3 on debian
-
- if (OSUtil.Linux.isDebian()) {
- // note: Debian Gnome3 does NOT work! (tested on Debian 8.5 and 8.6 default installs)
- logger.warn("Debian with Gnome detected. SystemTray support is not known to work.");
+ case KDE: {
+ if (OSUtil.Linux.isFedora()) {
+ // Fedora KDE requires GtkStatusIcon
+ trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ } else {
+ // kde (at least, plasma 5.5.6) requires appindicator
+ trayType = selectTypeQuietly(TrayType.AppIndicator);
}
- trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ // kde 5.8+ is "high DPI", so we need to adjust the scale. Image resize will do that
+ break;
}
- else if ("gnome-classic".equalsIgnoreCase(GDM)) {
- trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
- }
- else if ("gnome-fallback".equalsIgnoreCase(GDM)) {
- trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
- }
- else if ("ubuntu".equalsIgnoreCase(GDM)) {
+ case Unity: {
+ // Ubuntu Unity is a weird combination. It's "Gnome", but it's not "Gnome Shell".
trayType = selectTypeQuietly(TrayType.AppIndicator);
+ break;
+ }
+ case XFCE: {
+ // NOTE: XFCE used to use appindicator3, which DOES NOT support images in the menu. This change was reverted.
+ // see: https://ask.fedoraproject.org/en/question/23116/how-to-fix-missing-icons-in-program-menus-and-context-menus/
+ // see: https://git.gnome.org/browse/gtk+/commit/?id=627a03683f5f41efbfc86cc0f10e1b7c11e9bb25
+
+ // so far, it is OK to use GtkStatusIcon on XFCE <-> XFCE4 inclusive
+ trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ break;
+ }
+ case LXDE: {
+ trayType = selectTypeQuietly(TrayType.GtkStatusIcon);
+ break;
+ }
+ case Pantheon: {
+ // elementaryOS. It only supports appindicator (not gtkstatusicon)
+ // http://bazaar.launchpad.net/~wingpanel-devs/wingpanel/trunk/view/head:/sample/SampleIndicator.vala
+
+ // ElementaryOS shows the checkbox on the right, everyone else is on the left.
+ // With eOS, we CANNOT show the spacer image. It does not work.
+ trayType = selectTypeQuietly(TrayType.AppIndicator);
+ break;
}
}
}
@@ -620,39 +649,11 @@ class SystemTray {
return;
}
- if (isTrayType(trayType, TrayType.AppIndicator)) {
+ if (isTrayType(trayType, TrayType.AppIndicator) && OSUtil.Linux.isRoot()) {
// if are we running as ROOT, there can be issues (definitely on Ubuntu 16.04, maybe others)!
- // this means we are running as sudo
- String sudoUser = System.getenv("SUDO_USER");
- if (sudoUser != null) {
- // running as a "sudo" user
- logger.error("Attempting to load the SystemTray as the 'root' user. This will likely not work because of dbus restrictions.");
- }
- else {
- // running as root (also can be "sudo" user). A bit slower that checking a sys env, but this is guaranteed to work
- try {
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(8196);
- PrintStream outputStream = new PrintStream(byteArrayOutputStream);
-
- // id -u
- final ShellProcessBuilder shell = new ShellProcessBuilder(outputStream);
- shell.setExecutable("id");
- shell.addArgument("-u");
- shell.start();
-
-
- String output = ShellProcessBuilder.getOutput(byteArrayOutputStream);
- if ("0".equals(output)) {
- logger.error("Attempting to load the SystemTray as the 'root' user. This will likely not work because of dbus " +
- "restrictions.");
- }
- } catch (Throwable e) {
- if (DEBUG) {
- logger.error("Cannot get id for root", e);
- }
- }
- }
+ logger.error("Attempting to load the SystemTray as the 'root/sudo' user. This will likely not work because of dbus " +
+ "restrictions.");
}
}
@@ -666,8 +667,6 @@ class SystemTray {
return;
}
- ImageUtils.determineIconSize();
-
final AtomicReference
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imagePath the full path of the image to use or null
*/
@@ -1016,16 +1025,16 @@ class SystemTray {
throw new NullPointerException("imagePath cannot be null!");
}
- final Menu menu = systemTrayMenu;
- if (menu != null) {
- menu.setImage(imagePath);
+ final Tray tray = systemTrayMenu;
+ if (tray != null) {
+ tray.setImage(imagePath);
}
}
/**
- * Specifies the new image to set for a menu entry, NULL to delete the image
- *
- * This method will cache the image if it needs to be resized to fit.
+ * Specifies the new image to set for the tray icon.
+ *
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imageUrl the URL of the image to use or null
*/
@@ -1042,9 +1051,9 @@ class SystemTray {
}
/**
- * Specifies the new image to set for a menu entry, NULL to delete the image
+ * Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imageStream the InputStream of the image to use
*/
@@ -1061,9 +1070,9 @@ class SystemTray {
}
/**
- * Specifies the new image to set for a menu entry, NULL to delete the image
+ * Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param image the image of the image to use
*/
@@ -1080,9 +1089,9 @@ class SystemTray {
}
/**
- * Specifies the new image to set for a menu entry, NULL to delete the image
+ * Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
*@param imageStream the ImageInputStream of the image to use
*/
@@ -1092,10 +1101,27 @@ class SystemTray {
throw new NullPointerException("image cannot be null!");
}
- final Menu menu = systemTrayMenu;
- if (menu != null) {
- menu.setImage(imageStream);
+ final Tray tray = systemTrayMenu;
+ if (tray != null) {
+ tray.setImage(imageStream);
}
}
+
+ /**
+ * @return the system tray image size, accounting for OS and theme differences
+ */
+ public
+ int getTrayImageSize() {
+ return SizeAndScalingUtil.getTrayImageSize(systemTrayMenu.getClass());
+ }
+
+
+ /**
+ * @return the system tray menu image size, accounting for OS and theme differences
+ */
+ public
+ int getMenuImageSize() {
+ return SizeAndScalingUtil.getMenuImageSize(systemTrayMenu.getClass());
+ }
}
diff --git a/src/dorkbox/systemTray/Tray.java b/src/dorkbox/systemTray/Tray.java
index a3d199e..d99cfcd 100644
--- a/src/dorkbox/systemTray/Tray.java
+++ b/src/dorkbox/systemTray/Tray.java
@@ -23,7 +23,7 @@ import java.net.URL;
import javax.imageio.stream.ImageInputStream;
import dorkbox.systemTray.gnomeShell.Extension;
-import dorkbox.systemTray.util.ImageUtils;
+import dorkbox.systemTray.util.ImageResizeUtil;
import dorkbox.util.OSUtil;
// This is public ONLY so that it is in the scope for SwingUI and NativeUI system tray components
@@ -53,7 +53,7 @@ class Tray extends Menu {
}
}
- // appindicators DO NOT support anything other than PLAIN gtk-menus (which we hack to support swing menus)
+ // appindicators DO NOT support anything other than PLAIN gtk-menus
// they ALSO do not support tooltips!
// https://bugs.launchpad.net/indicator-application/+bug/527458/comments/12
@@ -142,72 +142,78 @@ class Tray extends Menu {
/**
* Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imageFile the file of the image to use
*/
+ @Override
public
void setImage(final File imageFile) {
- setImage_(ImageUtils.resizeAndCache(ImageUtils.TRAY_SIZE, imageFile));
+ setImage_(ImageResizeUtil.shouldResizeOrCache(true, imageFile));
}
/**
* Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imagePath the full path of the image to use
*/
+ @Override
public
void setImage(final String imagePath) {
- setImage_(ImageUtils.resizeAndCache(ImageUtils.TRAY_SIZE, imagePath));
+ setImage_(ImageResizeUtil.shouldResizeOrCache(true, imagePath));
}
/**
* Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imageUrl the URL of the image to use
*/
+ @Override
public
void setImage(final URL imageUrl) {
- setImage_(ImageUtils.resizeAndCache(ImageUtils.TRAY_SIZE, imageUrl));
+ setImage_(ImageResizeUtil.shouldResizeOrCache(true, imageUrl));
}
/**
* Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imageStream the InputStream of the image to use
*/
+ @Override
public
void setImage(final InputStream imageStream) {
- setImage_(ImageUtils.resizeAndCache(ImageUtils.TRAY_SIZE, imageStream));
+ setImage_(ImageResizeUtil.shouldResizeOrCache(true, imageStream));
}
/**
* Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param image the image of the image to use
*/
+ @Override
public
void setImage(final Image image) {
- setImage_(ImageUtils.resizeAndCache(ImageUtils.TRAY_SIZE, image));
+ setImage_(ImageResizeUtil.shouldResizeOrCache(true, image));
}
/**
* Specifies the new image to set for the tray icon.
*
- * This method will cache the image if it needs to be resized to fit.
+ * If AUTO_SIZE, then this method resize the image (best guess), otherwise the image "as-is" will be used
*
* @param imageStream the ImageInputStream of the image to use
*/
+ @Override
public
void setImage(final ImageInputStream imageStream) {
- setImage_(ImageUtils.resizeAndCache(ImageUtils.TRAY_SIZE, imageStream));
+ setImage_(ImageResizeUtil.shouldResizeOrCache(true, imageStream));
}
}