Fixed issues with loading libappindicator (for incorrect versions), now falls back to GTK. Compiled as java6.

This commit is contained in:
nathan 2015-06-28 01:47:02 +02:00
parent 2ff2366325
commit c692059150
8 changed files with 242 additions and 166 deletions

View File

@ -15,6 +15,7 @@
*/
package dorkbox.util.tray;
public interface FailureCallback {
public void createTrayFailed();
public
interface FailureCallback {
void createTrayFailed();
}

View File

@ -15,13 +15,17 @@
*/
package dorkbox.util.tray;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import dorkbox.util.NamedThreadFactory;
import dorkbox.util.OS;
import dorkbox.util.jna.linux.AppIndicator;
import dorkbox.util.jna.linux.GtkSupport;
import dorkbox.util.tray.linux.AppIndicatorTray;
import dorkbox.util.tray.linux.GtkSystemTray;
import dorkbox.util.tray.swing.SwingSystemTray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.math.BigInteger;
import java.net.URL;
import java.nio.ByteBuffer;
@ -32,21 +36,12 @@ import java.security.SecureRandom;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dorkbox.util.NamedThreadFactory;
import dorkbox.util.OS;
import dorkbox.util.jna.linux.GtkSupport;
import dorkbox.util.tray.linux.AppIndicatorTray;
import dorkbox.util.tray.linux.GtkSystemTray;
import dorkbox.util.tray.swing.SwingSystemTray;
/**
* Interface for system tray implementations.
*/
public abstract class SystemTray {
public abstract
class SystemTray {
private static final Charset UTF_8 = Charset.forName("UTF-8");
private static MessageDigest digest;
@ -80,7 +75,7 @@ public abstract class SystemTray {
if (getenv != null && getenv.equals("Unity")) {
try {
trayType = AppIndicatorTray.class;
} catch (Exception ignored) {
} catch (Throwable ignored) {
}
}
@ -107,7 +102,13 @@ public abstract class SystemTray {
bin = new BufferedReader(new FileReader(status));
String readLine = bin.readLine();
if (readLine != null && readLine.contains("indicator-app")) {
trayType = AppIndicatorTray.class;
// make sure we can also load the library (it might be the wrong version)
try {
final AppIndicator instance = AppIndicator.INSTANCE;
trayType = AppIndicatorTray.class;
} catch (Throwable ignored) {
logger.error("AppIndicator support detected, but unable to load the library. Falling back to GTK");
}
break;
}
} finally {
@ -118,7 +119,7 @@ public abstract class SystemTray {
}
}
}
} catch (Exception ignored) {
} catch (Throwable ignored) {
} finally {
if (bin != null) {
try {
@ -129,6 +130,7 @@ public abstract class SystemTray {
}
}
if (trayType == null) {
trayType = GtkSystemTray.class;
}
@ -143,7 +145,8 @@ public abstract class SystemTray {
if (trayType == null) {
// unsupported tray
logger.error("Unsupported tray type!");
} else {
}
else {
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
@ -159,7 +162,8 @@ public abstract class SystemTray {
protected volatile boolean active = false;
protected String appName;
public static SystemTray create(String appName) {
public static
SystemTray create(String appName) {
if (trayType != null) {
try {
SystemTray newInstance = trayType.newInstance();
@ -167,7 +171,7 @@ public abstract class SystemTray {
newInstance.setAppName(appName);
}
return newInstance;
} catch (Exception e) {
} catch (Throwable e) {
e.printStackTrace();
}
}
@ -176,34 +180,43 @@ public abstract class SystemTray {
return null;
}
private void setAppName(String appName) {
private
void setAppName(String appName) {
this.appName = appName;
}
public abstract void createTray(String iconName);
public abstract
void createTray(String iconName);
public void removeTray() {
public
void removeTray() {
SystemTray.this.callbackExecutor.shutdown();
}
public abstract void setStatus(String infoString, String iconName);
public abstract
void setStatus(String infoString, String iconName);
public abstract void addMenuEntry(String menuText, SystemTrayMenuAction callback);
public abstract
void addMenuEntry(String menuText, SystemTrayMenuAction callback);
public abstract void updateMenuEntry(String origMenuText, String newMenuText, SystemTrayMenuAction newCallback);
public abstract
void updateMenuEntry(String origMenuText, String newMenuText, SystemTrayMenuAction newCallback);
protected String iconPath(String fileName) {
protected
String iconPath(String fileName) {
// is file sitting on drive
File iconTest;
if (ICON_PATH.isEmpty()) {
iconTest = new File(fileName);
} else {
}
else {
iconTest = new File(ICON_PATH, fileName);
}
if (iconTest.isFile() && iconTest.canRead()) {
return iconTest.getAbsolutePath();
} else {
}
else {
if (!ICON_PATH.isEmpty()) {
fileName = ICON_PATH + "/" + fileName;
}
@ -291,11 +304,13 @@ public abstract class SystemTray {
throw new RuntimeException(message);
}
public final void setFailureCallback(FailureCallback failureCallback) {
public final
void setFailureCallback(FailureCallback failureCallback) {
this.failureCallback = failureCallback;
}
public final boolean isActive() {
public final
boolean isActive() {
return this.active;
}
}

View File

@ -15,6 +15,7 @@
*/
package dorkbox.util.tray;
public interface SystemTrayMenuAction {
public
interface SystemTrayMenuAction {
void onClick(SystemTray systemTray);
}

View File

@ -1,46 +1,50 @@
package dorkbox.util.tray;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPopupMenu;
import dorkbox.util.DelayTimer;
import dorkbox.util.SwingUtil;
public class SystemTrayMenuPopup extends JPopupMenu {
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public
class SystemTrayMenuPopup extends JPopupMenu {
private static final long serialVersionUID = 1L;
/** Allows you to customize the delay (for hiding the popup) when the cursor is "moused out" of the popup menu */
/**
* Allows you to customize the delay (for hiding the popup) when the cursor is "moused out" of the popup menu
*/
public static long hidePopupDelay = 1000L;
private DelayTimer timer;
protected boolean mouseStillOnMenu;
// protected boolean mouseStillOnMenu;
// private JDialog hiddenDialog;
public SystemTrayMenuPopup() {
public
SystemTrayMenuPopup() {
super();
setFocusable(true);
this.timer = new DelayTimer("PopupMenuHider", true, new DelayTimer.Callback() {
@Override
public void execute() {
public
void execute() {
SwingUtil.invokeLater(new Runnable() {
@Override
public void run() {
public
void run() {
Point location = MouseInfo.getPointerInfo().getLocation();
Point locationOnScreen = getLocationOnScreen();
Dimension size = getSize();
if (location.x >= locationOnScreen.x && location.x < locationOnScreen.x + size.width
&& location.y >= locationOnScreen.y && location.y < locationOnScreen.y + size.height) {
if (location.x >= locationOnScreen.x && location.x < locationOnScreen.x + size.width &&
location.y >= locationOnScreen.y && location.y < locationOnScreen.y + size.height) {
SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay());
} else {
}
else {
setVisible(false);
}
}
@ -50,7 +54,8 @@ public class SystemTrayMenuPopup extends JPopupMenu {
addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent event) {
public
void mouseExited(MouseEvent event) {
// wait before checking if mouse is still on the menu
SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay());
}
@ -75,7 +80,8 @@ public class SystemTrayMenuPopup extends JPopupMenu {
}
@Override
public void setVisible(boolean makeVisible) {
public
void setVisible(boolean makeVisible) {
this.timer.cancel();
if (makeVisible) {

View File

@ -15,13 +15,7 @@
*/
package dorkbox.util.tray.linux;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import dorkbox.util.jna.linux.AppIndicator;
import dorkbox.util.jna.linux.Gobject;
import dorkbox.util.jna.linux.Gtk;
@ -29,16 +23,22 @@ import dorkbox.util.jna.linux.GtkSupport;
import dorkbox.util.tray.SystemTray;
import dorkbox.util.tray.SystemTrayMenuAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Class for handling all system tray interactions.
*
* <p/>
* specialization for using app indicators in ubuntu unity
*
* <p/>
* Heavily modified from
*
* <p/>
* Lantern: https://github.com/getlantern/lantern/ Apache 2.0 License Copyright 2010 Brave New Software Project, Inc.
*/
public class AppIndicatorTray extends SystemTray {
public
class AppIndicatorTray extends SystemTray {
private static final AppIndicator libappindicator = AppIndicator.INSTANCE;
private static final Gobject libgobject = Gobject.INSTANCE;
private static final Gtk libgtk = Gtk.INSTANCE;
@ -54,29 +54,33 @@ public class AppIndicatorTray extends SystemTray {
private final List<Pointer> widgets = new ArrayList<Pointer>(4);
public AppIndicatorTray() {
public
AppIndicatorTray() {
}
@Override
public void createTray(String iconName) {
public
void createTray(String iconName) {
libgtk.gdk_threads_enter();
this.appIndicator =
libappindicator.app_indicator_new(this.appName, "indicator-messages-new", AppIndicator.CATEGORY_APPLICATION_STATUS);
this.appIndicator = libappindicator.app_indicator_new(this.appName, "indicator-messages-new",
AppIndicator.CATEGORY_APPLICATION_STATUS);
/*
* basically a hack -- we should subclass the AppIndicator type and override the fallback entry in the 'vtable', instead we just
* hack the app indicator class itself. Not an issue unless we need other appindicators.
*/
AppIndicator.AppIndicatorClassStruct aiclass =
new AppIndicator.AppIndicatorClassStruct(this.appIndicator.parent.g_type_instance.g_class);
AppIndicator.AppIndicatorClassStruct aiclass = new AppIndicator.AppIndicatorClassStruct(
this.appIndicator.parent.g_type_instance.g_class);
aiclass.fallback = new AppIndicator.Fallback() {
@Override
public Pointer callback(final AppIndicator.AppIndicatorInstanceStruct self) {
public
Pointer callback(final AppIndicator.AppIndicatorInstanceStruct self) {
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
public
void run() {
logger.warn("Failed to create appindicator system tray.");
if (AppIndicatorTray.this.failureCallback != null) {
@ -101,7 +105,8 @@ public class AppIndicatorTray extends SystemTray {
}
@Override
public void removeTray() {
public
void removeTray() {
libgtk.gdk_threads_enter();
for (Pointer widget : this.widgets) {
libgtk.gtk_widget_destroy(widget);
@ -135,14 +140,16 @@ public class AppIndicatorTray extends SystemTray {
}
@Override
public void setStatus(String infoString, String iconName) {
public
void setStatus(String infoString, String iconName) {
libgtk.gdk_threads_enter();
if (this.connectionStatusItem == null) {
this.connectionStatusItem = libgtk.gtk_menu_item_new_with_label(infoString);
this.widgets.add(this.connectionStatusItem);
libgtk.gtk_widget_set_sensitive(this.connectionStatusItem, Gtk.FALSE);
libgtk.gtk_menu_shell_append(this.menu, this.connectionStatusItem);
} else {
}
else {
libgtk.gtk_menu_item_set_label(this.connectionStatusItem, infoString);
}
@ -156,7 +163,8 @@ public class AppIndicatorTray extends SystemTray {
* Will add a new menu entry, or update one if it already exists
*/
@Override
public void addMenuEntry(String menuText, final SystemTrayMenuAction callback) {
public
void addMenuEntry(String menuText, final SystemTrayMenuAction callback) {
synchronized (this.menuEntries) {
MenuEntry menuEntry = this.menuEntries.get(menuText);
@ -168,10 +176,12 @@ public class AppIndicatorTray extends SystemTray {
// have to watch out! These can get garbage collected!
Gobject.GCallback gtkCallback = new Gobject.GCallback() {
@Override
public void callback(Pointer instance, Pointer data) {
public
void callback(Pointer instance, Pointer data) {
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
public
void run() {
callback.onClick(AppIndicatorTray.this);
}
});
@ -189,7 +199,8 @@ public class AppIndicatorTray extends SystemTray {
menuEntry.gtkCallback = gtkCallback;
this.menuEntries.put(menuText, menuEntry);
} else {
}
else {
updateMenuEntry(menuText, menuText, callback);
}
}
@ -199,7 +210,8 @@ public class AppIndicatorTray extends SystemTray {
* Will update an already existing menu entry (or add a new one, if it doesn't exist)
*/
@Override
public void updateMenuEntry(String origMenuText, String newMenuText, final SystemTrayMenuAction newCallback) {
public
void updateMenuEntry(String origMenuText, String newMenuText, final SystemTrayMenuAction newCallback) {
synchronized (this.menuEntries) {
MenuEntry menuEntry = this.menuEntries.get(origMenuText);
@ -210,10 +222,12 @@ public class AppIndicatorTray extends SystemTray {
// have to watch out! These can get garbage collected!
menuEntry.gtkCallback = new Gobject.GCallback() {
@Override
public void callback(Pointer instance, Pointer data) {
public
void callback(Pointer instance, Pointer data) {
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
public
void run() {
newCallback.onClick(AppIndicatorTray.this);
}
});
@ -224,7 +238,8 @@ public class AppIndicatorTray extends SystemTray {
libgtk.gtk_widget_show_all(menuEntry.dashboardItem);
libgtk.gdk_threads_leave();
} else {
}
else {
addMenuEntry(origMenuText, newCallback);
}
}

View File

@ -15,20 +15,7 @@
*/
package dorkbox.util.tray.linux;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JMenuItem;
import com.sun.jna.Pointer;
import dorkbox.util.SwingUtil;
import dorkbox.util.jna.linux.Gobject;
import dorkbox.util.jna.linux.Gtk;
@ -38,12 +25,22 @@ import dorkbox.util.tray.SystemTray;
import dorkbox.util.tray.SystemTrayMenuAction;
import dorkbox.util.tray.SystemTrayMenuPopup;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Class for handling all system tray interactions via GTK.
*
* <p/>
* This is the "old" way to do it, and does not work with some desktop environments.
*/
public class GtkSystemTray extends SystemTray {
public
class GtkSystemTray extends SystemTray {
private static final Gobject libgobject = Gobject.INSTANCE;
private static final Gtk libgtk = Gtk.INSTANCE;
@ -58,14 +55,17 @@ public class GtkSystemTray extends SystemTray {
private final List<Pointer> widgets = new ArrayList<Pointer>(4);
private Gobject.GEventCallback gtkCallback;
public GtkSystemTray() {
public
GtkSystemTray() {
}
@Override
public void createTray(String iconName) {
public
void createTray(String iconName) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
GtkSystemTray.this.jmenu = new SystemTrayMenuPopup();
}
});
@ -80,28 +80,32 @@ public class GtkSystemTray extends SystemTray {
// have to make this a field, to prevent GC on this object
this.gtkCallback = new Gobject.GEventCallback() {
@Override
public void callback(Pointer system_tray, final GdkEventButton event) {
public
void callback(Pointer system_tray, final GdkEventButton event) {
// BUTTON_PRESS only (any mouse click)
if (event.type == 4) {
SwingUtil.invokeLater(new Runnable() {
@Override
public void run() {
public
void run() {
// test this using cinnamon (which still uses status icon)
if (GtkSystemTray.this.jmenu.isVisible()) {
GtkSystemTray.this.jmenu.setVisible(false);
} else {
}
else {
Dimension size = GtkSystemTray.this.jmenu.getPreferredSize();
int x = (int) event.x_root;
int y = (int) event.y_root;
int y = (int) event.y_root;
Point point = new Point(x, y);
Rectangle bounds = SwingUtil.getScreenBoundsAt(point);
if (y < bounds.y) {
y = bounds.y;
} else if (y + size.height > bounds.y + bounds.height) {
}
else if (y + size.height > bounds.y + bounds.height) {
// our menu cannot have the top-edge snap to the mouse
// so we make the bottom-edge snap to the mouse
y -= size.height; // snap to edge of mouse
@ -109,7 +113,8 @@ public class GtkSystemTray extends SystemTray {
if (x < bounds.x) {
x = bounds.x;
} else if (x + size.width > bounds.x + bounds.width) {
}
else if (x + size.width > bounds.x + bounds.width) {
// our menu cannot have the left-edge snap to the mouse
// so we make the right-edge snap to the mouse
x -= size.width; // snap to edge of mouse
@ -122,7 +127,8 @@ public class GtkSystemTray extends SystemTray {
// we are at the top of the screen
if (y < 100) {
y += distanceToEdgeOfTray + 4;
} else {
}
else {
y -= distanceToEdgeOfTray + 4;
}
@ -144,7 +150,8 @@ public class GtkSystemTray extends SystemTray {
}
@Override
public void removeTray() {
public
void removeTray() {
libgtk.gdk_threads_enter();
for (Pointer widget : this.widgets) {
libgtk.gtk_widget_destroy(widget);
@ -177,15 +184,18 @@ public class GtkSystemTray extends SystemTray {
}
@Override
public void setStatus(final String infoString, String iconName) {
public
void setStatus(final String infoString, String iconName) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
if (GtkSystemTray.this.connectionStatusItem == null) {
GtkSystemTray.this.connectionStatusItem = new JMenuItem(infoString);
GtkSystemTray.this.connectionStatusItem.setEnabled(false);
GtkSystemTray.this.jmenu.add(GtkSystemTray.this.connectionStatusItem);
} else {
}
else {
GtkSystemTray.this.connectionStatusItem.setText(infoString);
}
}
@ -200,10 +210,12 @@ public class GtkSystemTray extends SystemTray {
* Will add a new menu entry, or update one if it already exists
*/
@Override
public void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
public
void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
Map<String, JMenuItem> menuEntries2 = GtkSystemTray.this.menuEntries;
synchronized (menuEntries2) {
@ -215,12 +227,14 @@ public class GtkSystemTray extends SystemTray {
menuEntry = new JMenuItem(menuText);
menuEntry.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
public
void actionPerformed(ActionEvent e) {
// SystemTrayMenuPopup source = (SystemTrayMenuPopup) ((JMenuItem)e.getSource()).getParent();
GtkSystemTray.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
public
void run() {
callback.onClick(GtkSystemTray.this);
}
});
@ -229,7 +243,8 @@ public class GtkSystemTray extends SystemTray {
menu.add(menuEntry);
menuEntries2.put(menuText, menuEntry);
} else {
}
else {
updateMenuEntry(menuText, menuText, callback);
}
}
@ -241,10 +256,12 @@ public class GtkSystemTray extends SystemTray {
* Will update an already existing menu entry (or add a new one, if it doesn't exist)
*/
@Override
public void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) {
public
void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
Map<String, JMenuItem> menuEntries2 = GtkSystemTray.this.menuEntries;
synchronized (menuEntries2) {
@ -258,10 +275,12 @@ public class GtkSystemTray extends SystemTray {
menuEntry.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
public
void actionPerformed(ActionEvent e) {
GtkSystemTray.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
public
void run() {
newCallback.onClick(GtkSystemTray.this);
}
});
@ -269,7 +288,8 @@ public class GtkSystemTray extends SystemTray {
});
menuEntry.setText(newMenuText);
menuEntry.revalidate();
} else {
}
else {
addMenuEntry(origMenuText, newCallback);
}
}

View File

@ -16,7 +16,6 @@
package dorkbox.util.tray.linux;
import com.sun.jna.Pointer;
import dorkbox.util.jna.linux.Gobject.GCallback;
/**
@ -28,18 +27,21 @@ class MenuEntry {
public Pointer dashboardItem;
public GCallback gtkCallback;
public MenuEntry() {
public
MenuEntry() {
long time = System.nanoTime();
this.hashCode = (int) (time ^ time >>> 32);
}
@Override
public int hashCode() {
public
int hashCode() {
return this.hashCode;
}
@Override
public boolean equals(Object obj) {
public
boolean equals(Object obj) {
if (this == obj) {
return true;
}

View File

@ -15,13 +15,12 @@
*/
package dorkbox.util.tray.swing;
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import dorkbox.util.SwingUtil;
import dorkbox.util.tray.SystemTrayMenuAction;
import dorkbox.util.tray.SystemTrayMenuPopup;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
@ -29,17 +28,11 @@ import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import dorkbox.util.SwingUtil;
import dorkbox.util.tray.SystemTrayMenuAction;
import dorkbox.util.tray.SystemTrayMenuPopup;
/**
* Class for handling all system tray interaction, via SWING
*/
public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
public
class SwingSystemTray extends dorkbox.util.tray.SystemTray {
private final Map<String, JMenuItem> menuEntries = new HashMap<String, JMenuItem>(2);
@ -52,14 +45,18 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
/**
* Creates a new system tray handler class.
*/
public SwingSystemTray() {}
public
SwingSystemTray() {
}
@Override
public void removeTray() {
public
void removeTray() {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
SwingSystemTray.this.tray.remove(SwingSystemTray.this.trayIcon);
SwingSystemTray.this.menuEntries.clear();
}
@ -69,14 +66,17 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
}
@Override
public void createTray(final String iconName) {
public
void createTray(final String iconName) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
SwingSystemTray.this.tray = SystemTray.getSystemTray();
if (SwingSystemTray.this.tray == null) {
logger.error("The system tray is not available");
} else {
}
else {
SwingSystemTray.this.jmenu = new SystemTrayMenuPopup();
Image trayImage = newImage(iconName);
@ -85,7 +85,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
SwingSystemTray.this.trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
public
void mousePressed(MouseEvent e) {
Dimension size = SwingSystemTray.this.jmenu.getPreferredSize();
Point point = e.getPoint();
@ -96,7 +97,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
if (y < bounds.y) {
y = bounds.y;
} else if (y + size.height > bounds.y + bounds.height) {
}
else if (y + size.height > bounds.y + bounds.height) {
// our menu cannot have the top-edge snap to the mouse
// so we make the bottom-edge snap to the mouse
y -= size.height; // snap to edge of mouse
@ -104,7 +106,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
if (x < bounds.x) {
x = bounds.x;
} else if (x + size.width > bounds.x + bounds.width) {
}
else if (x + size.width > bounds.x + bounds.width) {
// our menu cannot have the left-edge snap to the mouse
// so we make the right-edge snap to the mouse
x -= size.width; // snap to edge of mouse
@ -135,15 +138,18 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
}
@Override
public void setStatus(final String infoString, final String iconName) {
public
void setStatus(final String infoString, final String iconName) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
if (SwingSystemTray.this.connectionStatusItem == null) {
SwingSystemTray.this.connectionStatusItem = new JMenuItem(infoString);
SwingSystemTray.this.connectionStatusItem.setEnabled(false);
SwingSystemTray.this.jmenu.add(SwingSystemTray.this.connectionStatusItem);
} else {
}
else {
SwingSystemTray.this.connectionStatusItem.setText(infoString);
}
}
@ -157,10 +163,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
* Will add a new menu entry, or update one if it already exists
*/
@Override
public void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
public
void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
Map<String, JMenuItem> menuEntries2 = SwingSystemTray.this.menuEntries;
synchronized (menuEntries2) {
@ -172,10 +180,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
menuEntry = new JMenuItem(menuText);
menuEntry.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
public
void actionPerformed(ActionEvent e) {
SwingSystemTray.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
public
void run() {
callback.onClick(SwingSystemTray.this);
}
});
@ -184,7 +194,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
menu.add(menuEntry);
menuEntries2.put(menuText, menuEntry);
} else {
}
else {
updateMenuEntry(menuText, menuText, callback);
}
}
@ -196,10 +207,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
* Will update an already existing menu entry (or add a new one, if it doesn't exist)
*/
@Override
public void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) {
public
void updateMenuEntry(final String origMenuText, final String newMenuText, final SystemTrayMenuAction newCallback) {
SwingUtil.invokeAndWait(new Runnable() {
@Override
public void run() {
public
void run() {
Map<String, JMenuItem> menuEntries2 = SwingSystemTray.this.menuEntries;
synchronized (menuEntries2) {
@ -213,10 +226,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
menuEntry.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
public
void actionPerformed(ActionEvent e) {
SwingSystemTray.this.callbackExecutor.execute(new Runnable() {
@Override
public void run() {
public
void run() {
newCallback.onClick(SwingSystemTray.this);
}
});
@ -224,7 +239,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
});
menuEntry.setText(newMenuText);
menuEntry.revalidate();
} else {
}
else {
addMenuEntry(origMenuText, newCallback);
}
}