forked from dorkbox/SystemTray
Fixed issues with loading libappindicator (for incorrect versions), now falls back to GTK. Compiled as java6.
This commit is contained in:
parent
2ff2366325
commit
c692059150
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.tray;
|
package dorkbox.util.tray;
|
||||||
|
|
||||||
public interface FailureCallback {
|
public
|
||||||
public void createTrayFailed();
|
interface FailureCallback {
|
||||||
|
void createTrayFailed();
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.tray;
|
package dorkbox.util.tray;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import dorkbox.util.NamedThreadFactory;
|
||||||
import java.io.File;
|
import dorkbox.util.OS;
|
||||||
import java.io.FileOutputStream;
|
import dorkbox.util.jna.linux.AppIndicator;
|
||||||
import java.io.FileReader;
|
import dorkbox.util.jna.linux.GtkSupport;
|
||||||
import java.io.IOException;
|
import dorkbox.util.tray.linux.AppIndicatorTray;
|
||||||
import java.io.InputStream;
|
import dorkbox.util.tray.linux.GtkSystemTray;
|
||||||
import java.io.OutputStream;
|
import dorkbox.util.tray.swing.SwingSystemTray;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -32,21 +36,12 @@ import java.security.SecureRandom;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
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.
|
* 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 final Charset UTF_8 = Charset.forName("UTF-8");
|
||||||
private static MessageDigest digest;
|
private static MessageDigest digest;
|
||||||
@ -80,7 +75,7 @@ public abstract class SystemTray {
|
|||||||
if (getenv != null && getenv.equals("Unity")) {
|
if (getenv != null && getenv.equals("Unity")) {
|
||||||
try {
|
try {
|
||||||
trayType = AppIndicatorTray.class;
|
trayType = AppIndicatorTray.class;
|
||||||
} catch (Exception ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +102,13 @@ public abstract class SystemTray {
|
|||||||
bin = new BufferedReader(new FileReader(status));
|
bin = new BufferedReader(new FileReader(status));
|
||||||
String readLine = bin.readLine();
|
String readLine = bin.readLine();
|
||||||
if (readLine != null && readLine.contains("indicator-app")) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -118,7 +119,7 @@ public abstract class SystemTray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Throwable ignored) {
|
||||||
} finally {
|
} finally {
|
||||||
if (bin != null) {
|
if (bin != null) {
|
||||||
try {
|
try {
|
||||||
@ -129,6 +130,7 @@ public abstract class SystemTray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (trayType == null) {
|
if (trayType == null) {
|
||||||
trayType = GtkSystemTray.class;
|
trayType = GtkSystemTray.class;
|
||||||
}
|
}
|
||||||
@ -143,7 +145,8 @@ public abstract class SystemTray {
|
|||||||
if (trayType == null) {
|
if (trayType == null) {
|
||||||
// unsupported tray
|
// unsupported tray
|
||||||
logger.error("Unsupported tray type!");
|
logger.error("Unsupported tray type!");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
try {
|
try {
|
||||||
digest = MessageDigest.getInstance("MD5");
|
digest = MessageDigest.getInstance("MD5");
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
@ -159,7 +162,8 @@ public abstract class SystemTray {
|
|||||||
protected volatile boolean active = false;
|
protected volatile boolean active = false;
|
||||||
protected String appName;
|
protected String appName;
|
||||||
|
|
||||||
public static SystemTray create(String appName) {
|
public static
|
||||||
|
SystemTray create(String appName) {
|
||||||
if (trayType != null) {
|
if (trayType != null) {
|
||||||
try {
|
try {
|
||||||
SystemTray newInstance = trayType.newInstance();
|
SystemTray newInstance = trayType.newInstance();
|
||||||
@ -167,7 +171,7 @@ public abstract class SystemTray {
|
|||||||
newInstance.setAppName(appName);
|
newInstance.setAppName(appName);
|
||||||
}
|
}
|
||||||
return newInstance;
|
return newInstance;
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,34 +180,43 @@ public abstract class SystemTray {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAppName(String appName) {
|
private
|
||||||
|
void setAppName(String appName) {
|
||||||
this.appName = 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();
|
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
|
// is file sitting on drive
|
||||||
File iconTest;
|
File iconTest;
|
||||||
if (ICON_PATH.isEmpty()) {
|
if (ICON_PATH.isEmpty()) {
|
||||||
iconTest = new File(fileName);
|
iconTest = new File(fileName);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
iconTest = new File(ICON_PATH, fileName);
|
iconTest = new File(ICON_PATH, fileName);
|
||||||
}
|
}
|
||||||
if (iconTest.isFile() && iconTest.canRead()) {
|
if (iconTest.isFile() && iconTest.canRead()) {
|
||||||
return iconTest.getAbsolutePath();
|
return iconTest.getAbsolutePath();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (!ICON_PATH.isEmpty()) {
|
if (!ICON_PATH.isEmpty()) {
|
||||||
fileName = ICON_PATH + "/" + fileName;
|
fileName = ICON_PATH + "/" + fileName;
|
||||||
}
|
}
|
||||||
@ -291,11 +304,13 @@ public abstract class SystemTray {
|
|||||||
throw new RuntimeException(message);
|
throw new RuntimeException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setFailureCallback(FailureCallback failureCallback) {
|
public final
|
||||||
|
void setFailureCallback(FailureCallback failureCallback) {
|
||||||
this.failureCallback = failureCallback;
|
this.failureCallback = failureCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isActive() {
|
public final
|
||||||
|
boolean isActive() {
|
||||||
return this.active;
|
return this.active;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.tray;
|
package dorkbox.util.tray;
|
||||||
|
|
||||||
public interface SystemTrayMenuAction {
|
public
|
||||||
|
interface SystemTrayMenuAction {
|
||||||
void onClick(SystemTray systemTray);
|
void onClick(SystemTray systemTray);
|
||||||
}
|
}
|
||||||
|
@ -1,46 +1,50 @@
|
|||||||
package dorkbox.util.tray;
|
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.DelayTimer;
|
||||||
import dorkbox.util.SwingUtil;
|
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;
|
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;
|
public static long hidePopupDelay = 1000L;
|
||||||
|
|
||||||
private DelayTimer timer;
|
private DelayTimer timer;
|
||||||
|
|
||||||
protected boolean mouseStillOnMenu;
|
// protected boolean mouseStillOnMenu;
|
||||||
// private JDialog hiddenDialog;
|
// private JDialog hiddenDialog;
|
||||||
|
|
||||||
public SystemTrayMenuPopup() {
|
public
|
||||||
|
SystemTrayMenuPopup() {
|
||||||
super();
|
super();
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
|
|
||||||
this.timer = new DelayTimer("PopupMenuHider", true, new DelayTimer.Callback() {
|
this.timer = new DelayTimer("PopupMenuHider", true, new DelayTimer.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public
|
||||||
|
void execute() {
|
||||||
SwingUtil.invokeLater(new Runnable() {
|
SwingUtil.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
Point location = MouseInfo.getPointerInfo().getLocation();
|
Point location = MouseInfo.getPointerInfo().getLocation();
|
||||||
Point locationOnScreen = getLocationOnScreen();
|
Point locationOnScreen = getLocationOnScreen();
|
||||||
Dimension size = getSize();
|
Dimension size = getSize();
|
||||||
|
|
||||||
if (location.x >= locationOnScreen.x && location.x < locationOnScreen.x + size.width
|
if (location.x >= locationOnScreen.x && location.x < locationOnScreen.x + size.width &&
|
||||||
&& location.y >= locationOnScreen.y && location.y < locationOnScreen.y + size.height) {
|
location.y >= locationOnScreen.y && location.y < locationOnScreen.y + size.height) {
|
||||||
|
|
||||||
SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay());
|
SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +54,8 @@ public class SystemTrayMenuPopup extends JPopupMenu {
|
|||||||
|
|
||||||
addMouseListener(new MouseAdapter() {
|
addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(MouseEvent event) {
|
public
|
||||||
|
void mouseExited(MouseEvent event) {
|
||||||
// wait before checking if mouse is still on the menu
|
// wait before checking if mouse is still on the menu
|
||||||
SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay());
|
SystemTrayMenuPopup.this.timer.delay(SystemTrayMenuPopup.this.timer.getDelay());
|
||||||
}
|
}
|
||||||
@ -75,7 +80,8 @@ public class SystemTrayMenuPopup extends JPopupMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVisible(boolean makeVisible) {
|
public
|
||||||
|
void setVisible(boolean makeVisible) {
|
||||||
this.timer.cancel();
|
this.timer.cancel();
|
||||||
|
|
||||||
if (makeVisible) {
|
if (makeVisible) {
|
||||||
|
@ -15,13 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.tray.linux;
|
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 com.sun.jna.Pointer;
|
||||||
|
|
||||||
import dorkbox.util.jna.linux.AppIndicator;
|
import dorkbox.util.jna.linux.AppIndicator;
|
||||||
import dorkbox.util.jna.linux.Gobject;
|
import dorkbox.util.jna.linux.Gobject;
|
||||||
import dorkbox.util.jna.linux.Gtk;
|
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.SystemTray;
|
||||||
import dorkbox.util.tray.SystemTrayMenuAction;
|
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.
|
* Class for handling all system tray interactions.
|
||||||
*
|
* <p/>
|
||||||
* specialization for using app indicators in ubuntu unity
|
* specialization for using app indicators in ubuntu unity
|
||||||
*
|
* <p/>
|
||||||
* Heavily modified from
|
* Heavily modified from
|
||||||
*
|
* <p/>
|
||||||
* Lantern: https://github.com/getlantern/lantern/ Apache 2.0 License Copyright 2010 Brave New Software Project, Inc.
|
* 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 AppIndicator libappindicator = AppIndicator.INSTANCE;
|
||||||
private static final Gobject libgobject = Gobject.INSTANCE;
|
private static final Gobject libgobject = Gobject.INSTANCE;
|
||||||
private static final Gtk libgtk = Gtk.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);
|
private final List<Pointer> widgets = new ArrayList<Pointer>(4);
|
||||||
|
|
||||||
|
|
||||||
public AppIndicatorTray() {
|
public
|
||||||
|
AppIndicatorTray() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createTray(String iconName) {
|
public
|
||||||
|
void createTray(String iconName) {
|
||||||
libgtk.gdk_threads_enter();
|
libgtk.gdk_threads_enter();
|
||||||
this.appIndicator =
|
this.appIndicator = libappindicator.app_indicator_new(this.appName, "indicator-messages-new",
|
||||||
libappindicator.app_indicator_new(this.appName, "indicator-messages-new", AppIndicator.CATEGORY_APPLICATION_STATUS);
|
AppIndicator.CATEGORY_APPLICATION_STATUS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* basically a hack -- we should subclass the AppIndicator type and override the fallback entry in the 'vtable', instead we just
|
* 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.
|
* hack the app indicator class itself. Not an issue unless we need other appindicators.
|
||||||
*/
|
*/
|
||||||
AppIndicator.AppIndicatorClassStruct aiclass =
|
AppIndicator.AppIndicatorClassStruct aiclass = new AppIndicator.AppIndicatorClassStruct(
|
||||||
new AppIndicator.AppIndicatorClassStruct(this.appIndicator.parent.g_type_instance.g_class);
|
this.appIndicator.parent.g_type_instance.g_class);
|
||||||
|
|
||||||
|
|
||||||
aiclass.fallback = new AppIndicator.Fallback() {
|
aiclass.fallback = new AppIndicator.Fallback() {
|
||||||
@Override
|
@Override
|
||||||
public Pointer callback(final AppIndicator.AppIndicatorInstanceStruct self) {
|
public
|
||||||
|
Pointer callback(final AppIndicator.AppIndicatorInstanceStruct self) {
|
||||||
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
|
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
logger.warn("Failed to create appindicator system tray.");
|
logger.warn("Failed to create appindicator system tray.");
|
||||||
|
|
||||||
if (AppIndicatorTray.this.failureCallback != null) {
|
if (AppIndicatorTray.this.failureCallback != null) {
|
||||||
@ -101,7 +105,8 @@ public class AppIndicatorTray extends SystemTray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTray() {
|
public
|
||||||
|
void removeTray() {
|
||||||
libgtk.gdk_threads_enter();
|
libgtk.gdk_threads_enter();
|
||||||
for (Pointer widget : this.widgets) {
|
for (Pointer widget : this.widgets) {
|
||||||
libgtk.gtk_widget_destroy(widget);
|
libgtk.gtk_widget_destroy(widget);
|
||||||
@ -135,14 +140,16 @@ public class AppIndicatorTray extends SystemTray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(String infoString, String iconName) {
|
public
|
||||||
|
void setStatus(String infoString, String iconName) {
|
||||||
libgtk.gdk_threads_enter();
|
libgtk.gdk_threads_enter();
|
||||||
if (this.connectionStatusItem == null) {
|
if (this.connectionStatusItem == null) {
|
||||||
this.connectionStatusItem = libgtk.gtk_menu_item_new_with_label(infoString);
|
this.connectionStatusItem = libgtk.gtk_menu_item_new_with_label(infoString);
|
||||||
this.widgets.add(this.connectionStatusItem);
|
this.widgets.add(this.connectionStatusItem);
|
||||||
libgtk.gtk_widget_set_sensitive(this.connectionStatusItem, Gtk.FALSE);
|
libgtk.gtk_widget_set_sensitive(this.connectionStatusItem, Gtk.FALSE);
|
||||||
libgtk.gtk_menu_shell_append(this.menu, this.connectionStatusItem);
|
libgtk.gtk_menu_shell_append(this.menu, this.connectionStatusItem);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
libgtk.gtk_menu_item_set_label(this.connectionStatusItem, infoString);
|
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
|
* Will add a new menu entry, or update one if it already exists
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addMenuEntry(String menuText, final SystemTrayMenuAction callback) {
|
public
|
||||||
|
void addMenuEntry(String menuText, final SystemTrayMenuAction callback) {
|
||||||
synchronized (this.menuEntries) {
|
synchronized (this.menuEntries) {
|
||||||
MenuEntry menuEntry = this.menuEntries.get(menuText);
|
MenuEntry menuEntry = this.menuEntries.get(menuText);
|
||||||
|
|
||||||
@ -168,10 +176,12 @@ public class AppIndicatorTray extends SystemTray {
|
|||||||
// have to watch out! These can get garbage collected!
|
// have to watch out! These can get garbage collected!
|
||||||
Gobject.GCallback gtkCallback = new Gobject.GCallback() {
|
Gobject.GCallback gtkCallback = new Gobject.GCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void callback(Pointer instance, Pointer data) {
|
public
|
||||||
|
void callback(Pointer instance, Pointer data) {
|
||||||
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
|
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
callback.onClick(AppIndicatorTray.this);
|
callback.onClick(AppIndicatorTray.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -189,7 +199,8 @@ public class AppIndicatorTray extends SystemTray {
|
|||||||
menuEntry.gtkCallback = gtkCallback;
|
menuEntry.gtkCallback = gtkCallback;
|
||||||
|
|
||||||
this.menuEntries.put(menuText, menuEntry);
|
this.menuEntries.put(menuText, menuEntry);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
updateMenuEntry(menuText, menuText, callback);
|
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)
|
* Will update an already existing menu entry (or add a new one, if it doesn't exist)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void updateMenuEntry(String origMenuText, String newMenuText, final SystemTrayMenuAction newCallback) {
|
public
|
||||||
|
void updateMenuEntry(String origMenuText, String newMenuText, final SystemTrayMenuAction newCallback) {
|
||||||
synchronized (this.menuEntries) {
|
synchronized (this.menuEntries) {
|
||||||
MenuEntry menuEntry = this.menuEntries.get(origMenuText);
|
MenuEntry menuEntry = this.menuEntries.get(origMenuText);
|
||||||
|
|
||||||
@ -210,10 +222,12 @@ public class AppIndicatorTray extends SystemTray {
|
|||||||
// have to watch out! These can get garbage collected!
|
// have to watch out! These can get garbage collected!
|
||||||
menuEntry.gtkCallback = new Gobject.GCallback() {
|
menuEntry.gtkCallback = new Gobject.GCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void callback(Pointer instance, Pointer data) {
|
public
|
||||||
|
void callback(Pointer instance, Pointer data) {
|
||||||
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
|
AppIndicatorTray.this.callbackExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
newCallback.onClick(AppIndicatorTray.this);
|
newCallback.onClick(AppIndicatorTray.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -224,7 +238,8 @@ public class AppIndicatorTray extends SystemTray {
|
|||||||
|
|
||||||
libgtk.gtk_widget_show_all(menuEntry.dashboardItem);
|
libgtk.gtk_widget_show_all(menuEntry.dashboardItem);
|
||||||
libgtk.gdk_threads_leave();
|
libgtk.gdk_threads_leave();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
addMenuEntry(origMenuText, newCallback);
|
addMenuEntry(origMenuText, newCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,20 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.tray.linux;
|
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 com.sun.jna.Pointer;
|
||||||
|
|
||||||
import dorkbox.util.SwingUtil;
|
import dorkbox.util.SwingUtil;
|
||||||
import dorkbox.util.jna.linux.Gobject;
|
import dorkbox.util.jna.linux.Gobject;
|
||||||
import dorkbox.util.jna.linux.Gtk;
|
import dorkbox.util.jna.linux.Gtk;
|
||||||
@ -38,12 +25,22 @@ import dorkbox.util.tray.SystemTray;
|
|||||||
import dorkbox.util.tray.SystemTrayMenuAction;
|
import dorkbox.util.tray.SystemTrayMenuAction;
|
||||||
import dorkbox.util.tray.SystemTrayMenuPopup;
|
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.
|
* 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.
|
* 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 Gobject libgobject = Gobject.INSTANCE;
|
||||||
private static final Gtk libgtk = Gtk.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 final List<Pointer> widgets = new ArrayList<Pointer>(4);
|
||||||
private Gobject.GEventCallback gtkCallback;
|
private Gobject.GEventCallback gtkCallback;
|
||||||
|
|
||||||
public GtkSystemTray() {
|
public
|
||||||
|
GtkSystemTray() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createTray(String iconName) {
|
public
|
||||||
|
void createTray(String iconName) {
|
||||||
SwingUtil.invokeAndWait(new Runnable() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
GtkSystemTray.this.jmenu = new SystemTrayMenuPopup();
|
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
|
// have to make this a field, to prevent GC on this object
|
||||||
this.gtkCallback = new Gobject.GEventCallback() {
|
this.gtkCallback = new Gobject.GEventCallback() {
|
||||||
@Override
|
@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)
|
// BUTTON_PRESS only (any mouse click)
|
||||||
if (event.type == 4) {
|
if (event.type == 4) {
|
||||||
SwingUtil.invokeLater(new Runnable() {
|
SwingUtil.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
// test this using cinnamon (which still uses status icon)
|
// test this using cinnamon (which still uses status icon)
|
||||||
|
|
||||||
if (GtkSystemTray.this.jmenu.isVisible()) {
|
if (GtkSystemTray.this.jmenu.isVisible()) {
|
||||||
GtkSystemTray.this.jmenu.setVisible(false);
|
GtkSystemTray.this.jmenu.setVisible(false);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Dimension size = GtkSystemTray.this.jmenu.getPreferredSize();
|
Dimension size = GtkSystemTray.this.jmenu.getPreferredSize();
|
||||||
|
|
||||||
int x = (int) event.x_root;
|
int x = (int) event.x_root;
|
||||||
int y = (int) event.y_root;
|
int y = (int) event.y_root;
|
||||||
|
|
||||||
Point point = new Point(x, y);
|
Point point = new Point(x, y);
|
||||||
Rectangle bounds = SwingUtil.getScreenBoundsAt(point);
|
Rectangle bounds = SwingUtil.getScreenBoundsAt(point);
|
||||||
|
|
||||||
if (y < bounds.y) {
|
if (y < bounds.y) {
|
||||||
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
|
// our menu cannot have the top-edge snap to the mouse
|
||||||
// so we make the bottom-edge snap to the mouse
|
// so we make the bottom-edge snap to the mouse
|
||||||
y -= size.height; // snap to edge of mouse
|
y -= size.height; // snap to edge of mouse
|
||||||
@ -109,7 +113,8 @@ public class GtkSystemTray extends SystemTray {
|
|||||||
|
|
||||||
if (x < bounds.x) {
|
if (x < bounds.x) {
|
||||||
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
|
// our menu cannot have the left-edge snap to the mouse
|
||||||
// so we make the right-edge snap to the mouse
|
// so we make the right-edge snap to the mouse
|
||||||
x -= size.width; // snap to edge of 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
|
// we are at the top of the screen
|
||||||
if (y < 100) {
|
if (y < 100) {
|
||||||
y += distanceToEdgeOfTray + 4;
|
y += distanceToEdgeOfTray + 4;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
y -= distanceToEdgeOfTray + 4;
|
y -= distanceToEdgeOfTray + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +150,8 @@ public class GtkSystemTray extends SystemTray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTray() {
|
public
|
||||||
|
void removeTray() {
|
||||||
libgtk.gdk_threads_enter();
|
libgtk.gdk_threads_enter();
|
||||||
for (Pointer widget : this.widgets) {
|
for (Pointer widget : this.widgets) {
|
||||||
libgtk.gtk_widget_destroy(widget);
|
libgtk.gtk_widget_destroy(widget);
|
||||||
@ -177,15 +184,18 @@ public class GtkSystemTray extends SystemTray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(final String infoString, String iconName) {
|
public
|
||||||
|
void setStatus(final String infoString, String iconName) {
|
||||||
SwingUtil.invokeAndWait(new Runnable() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
if (GtkSystemTray.this.connectionStatusItem == null) {
|
if (GtkSystemTray.this.connectionStatusItem == null) {
|
||||||
GtkSystemTray.this.connectionStatusItem = new JMenuItem(infoString);
|
GtkSystemTray.this.connectionStatusItem = new JMenuItem(infoString);
|
||||||
GtkSystemTray.this.connectionStatusItem.setEnabled(false);
|
GtkSystemTray.this.connectionStatusItem.setEnabled(false);
|
||||||
GtkSystemTray.this.jmenu.add(GtkSystemTray.this.connectionStatusItem);
|
GtkSystemTray.this.jmenu.add(GtkSystemTray.this.connectionStatusItem);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
GtkSystemTray.this.connectionStatusItem.setText(infoString);
|
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
|
* Will add a new menu entry, or update one if it already exists
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
|
public
|
||||||
|
void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
|
||||||
SwingUtil.invokeAndWait(new Runnable() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
Map<String, JMenuItem> menuEntries2 = GtkSystemTray.this.menuEntries;
|
Map<String, JMenuItem> menuEntries2 = GtkSystemTray.this.menuEntries;
|
||||||
|
|
||||||
synchronized (menuEntries2) {
|
synchronized (menuEntries2) {
|
||||||
@ -215,12 +227,14 @@ public class GtkSystemTray extends SystemTray {
|
|||||||
menuEntry = new JMenuItem(menuText);
|
menuEntry = new JMenuItem(menuText);
|
||||||
menuEntry.addActionListener(new ActionListener() {
|
menuEntry.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public
|
||||||
|
void actionPerformed(ActionEvent e) {
|
||||||
// SystemTrayMenuPopup source = (SystemTrayMenuPopup) ((JMenuItem)e.getSource()).getParent();
|
// SystemTrayMenuPopup source = (SystemTrayMenuPopup) ((JMenuItem)e.getSource()).getParent();
|
||||||
|
|
||||||
GtkSystemTray.this.callbackExecutor.execute(new Runnable() {
|
GtkSystemTray.this.callbackExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
callback.onClick(GtkSystemTray.this);
|
callback.onClick(GtkSystemTray.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -229,7 +243,8 @@ public class GtkSystemTray extends SystemTray {
|
|||||||
menu.add(menuEntry);
|
menu.add(menuEntry);
|
||||||
|
|
||||||
menuEntries2.put(menuText, menuEntry);
|
menuEntries2.put(menuText, menuEntry);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
updateMenuEntry(menuText, menuText, callback);
|
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)
|
* Will update an already existing menu entry (or add a new one, if it doesn't exist)
|
||||||
*/
|
*/
|
||||||
@Override
|
@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() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
Map<String, JMenuItem> menuEntries2 = GtkSystemTray.this.menuEntries;
|
Map<String, JMenuItem> menuEntries2 = GtkSystemTray.this.menuEntries;
|
||||||
|
|
||||||
synchronized (menuEntries2) {
|
synchronized (menuEntries2) {
|
||||||
@ -258,10 +275,12 @@ public class GtkSystemTray extends SystemTray {
|
|||||||
|
|
||||||
menuEntry.addActionListener(new ActionListener() {
|
menuEntry.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public
|
||||||
|
void actionPerformed(ActionEvent e) {
|
||||||
GtkSystemTray.this.callbackExecutor.execute(new Runnable() {
|
GtkSystemTray.this.callbackExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
newCallback.onClick(GtkSystemTray.this);
|
newCallback.onClick(GtkSystemTray.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -269,7 +288,8 @@ public class GtkSystemTray extends SystemTray {
|
|||||||
});
|
});
|
||||||
menuEntry.setText(newMenuText);
|
menuEntry.setText(newMenuText);
|
||||||
menuEntry.revalidate();
|
menuEntry.revalidate();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
addMenuEntry(origMenuText, newCallback);
|
addMenuEntry(origMenuText, newCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package dorkbox.util.tray.linux;
|
package dorkbox.util.tray.linux;
|
||||||
|
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
import dorkbox.util.jna.linux.Gobject.GCallback;
|
import dorkbox.util.jna.linux.Gobject.GCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,18 +27,21 @@ class MenuEntry {
|
|||||||
public Pointer dashboardItem;
|
public Pointer dashboardItem;
|
||||||
public GCallback gtkCallback;
|
public GCallback gtkCallback;
|
||||||
|
|
||||||
public MenuEntry() {
|
public
|
||||||
|
MenuEntry() {
|
||||||
long time = System.nanoTime();
|
long time = System.nanoTime();
|
||||||
this.hashCode = (int) (time ^ time >>> 32);
|
this.hashCode = (int) (time ^ time >>> 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public
|
||||||
|
int hashCode() {
|
||||||
return this.hashCode;
|
return this.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public
|
||||||
|
boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.tray.swing;
|
package dorkbox.util.tray.swing;
|
||||||
|
|
||||||
import java.awt.AWTException;
|
import dorkbox.util.SwingUtil;
|
||||||
import java.awt.Dimension;
|
import dorkbox.util.tray.SystemTrayMenuAction;
|
||||||
import java.awt.Image;
|
import dorkbox.util.tray.SystemTrayMenuPopup;
|
||||||
import java.awt.Point;
|
|
||||||
import java.awt.Rectangle;
|
import javax.swing.*;
|
||||||
import java.awt.SystemTray;
|
import java.awt.*;
|
||||||
import java.awt.TrayIcon;
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
@ -29,17 +28,11 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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
|
* 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);
|
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.
|
* Creates a new system tray handler class.
|
||||||
*/
|
*/
|
||||||
public SwingSystemTray() {}
|
public
|
||||||
|
SwingSystemTray() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTray() {
|
public
|
||||||
|
void removeTray() {
|
||||||
SwingUtil.invokeAndWait(new Runnable() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
SwingSystemTray.this.tray.remove(SwingSystemTray.this.trayIcon);
|
SwingSystemTray.this.tray.remove(SwingSystemTray.this.trayIcon);
|
||||||
SwingSystemTray.this.menuEntries.clear();
|
SwingSystemTray.this.menuEntries.clear();
|
||||||
}
|
}
|
||||||
@ -69,14 +66,17 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createTray(final String iconName) {
|
public
|
||||||
|
void createTray(final String iconName) {
|
||||||
SwingUtil.invokeAndWait(new Runnable() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
SwingSystemTray.this.tray = SystemTray.getSystemTray();
|
SwingSystemTray.this.tray = SystemTray.getSystemTray();
|
||||||
if (SwingSystemTray.this.tray == null) {
|
if (SwingSystemTray.this.tray == null) {
|
||||||
logger.error("The system tray is not available");
|
logger.error("The system tray is not available");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
SwingSystemTray.this.jmenu = new SystemTrayMenuPopup();
|
SwingSystemTray.this.jmenu = new SystemTrayMenuPopup();
|
||||||
|
|
||||||
Image trayImage = newImage(iconName);
|
Image trayImage = newImage(iconName);
|
||||||
@ -85,7 +85,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
|
|
||||||
SwingSystemTray.this.trayIcon.addMouseListener(new MouseAdapter() {
|
SwingSystemTray.this.trayIcon.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public
|
||||||
|
void mousePressed(MouseEvent e) {
|
||||||
Dimension size = SwingSystemTray.this.jmenu.getPreferredSize();
|
Dimension size = SwingSystemTray.this.jmenu.getPreferredSize();
|
||||||
|
|
||||||
Point point = e.getPoint();
|
Point point = e.getPoint();
|
||||||
@ -96,7 +97,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
|
|
||||||
if (y < bounds.y) {
|
if (y < bounds.y) {
|
||||||
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
|
// our menu cannot have the top-edge snap to the mouse
|
||||||
// so we make the bottom-edge snap to the mouse
|
// so we make the bottom-edge snap to the mouse
|
||||||
y -= size.height; // snap to edge of 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) {
|
if (x < bounds.x) {
|
||||||
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
|
// our menu cannot have the left-edge snap to the mouse
|
||||||
// so we make the right-edge snap to the mouse
|
// so we make the right-edge snap to the mouse
|
||||||
x -= size.width; // snap to edge of mouse
|
x -= size.width; // snap to edge of mouse
|
||||||
@ -135,15 +138,18 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(final String infoString, final String iconName) {
|
public
|
||||||
|
void setStatus(final String infoString, final String iconName) {
|
||||||
SwingUtil.invokeAndWait(new Runnable() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
if (SwingSystemTray.this.connectionStatusItem == null) {
|
if (SwingSystemTray.this.connectionStatusItem == null) {
|
||||||
SwingSystemTray.this.connectionStatusItem = new JMenuItem(infoString);
|
SwingSystemTray.this.connectionStatusItem = new JMenuItem(infoString);
|
||||||
SwingSystemTray.this.connectionStatusItem.setEnabled(false);
|
SwingSystemTray.this.connectionStatusItem.setEnabled(false);
|
||||||
SwingSystemTray.this.jmenu.add(SwingSystemTray.this.connectionStatusItem);
|
SwingSystemTray.this.jmenu.add(SwingSystemTray.this.connectionStatusItem);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
SwingSystemTray.this.connectionStatusItem.setText(infoString);
|
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
|
* Will add a new menu entry, or update one if it already exists
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
|
public
|
||||||
|
void addMenuEntry(final String menuText, final SystemTrayMenuAction callback) {
|
||||||
SwingUtil.invokeAndWait(new Runnable() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
Map<String, JMenuItem> menuEntries2 = SwingSystemTray.this.menuEntries;
|
Map<String, JMenuItem> menuEntries2 = SwingSystemTray.this.menuEntries;
|
||||||
|
|
||||||
synchronized (menuEntries2) {
|
synchronized (menuEntries2) {
|
||||||
@ -172,10 +180,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
menuEntry = new JMenuItem(menuText);
|
menuEntry = new JMenuItem(menuText);
|
||||||
menuEntry.addActionListener(new ActionListener() {
|
menuEntry.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public
|
||||||
|
void actionPerformed(ActionEvent e) {
|
||||||
SwingSystemTray.this.callbackExecutor.execute(new Runnable() {
|
SwingSystemTray.this.callbackExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
callback.onClick(SwingSystemTray.this);
|
callback.onClick(SwingSystemTray.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -184,7 +194,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
menu.add(menuEntry);
|
menu.add(menuEntry);
|
||||||
|
|
||||||
menuEntries2.put(menuText, menuEntry);
|
menuEntries2.put(menuText, menuEntry);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
updateMenuEntry(menuText, menuText, callback);
|
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)
|
* Will update an already existing menu entry (or add a new one, if it doesn't exist)
|
||||||
*/
|
*/
|
||||||
@Override
|
@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() {
|
SwingUtil.invokeAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
Map<String, JMenuItem> menuEntries2 = SwingSystemTray.this.menuEntries;
|
Map<String, JMenuItem> menuEntries2 = SwingSystemTray.this.menuEntries;
|
||||||
|
|
||||||
synchronized (menuEntries2) {
|
synchronized (menuEntries2) {
|
||||||
@ -213,10 +226,12 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
|
|
||||||
menuEntry.addActionListener(new ActionListener() {
|
menuEntry.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public
|
||||||
|
void actionPerformed(ActionEvent e) {
|
||||||
SwingSystemTray.this.callbackExecutor.execute(new Runnable() {
|
SwingSystemTray.this.callbackExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public
|
||||||
|
void run() {
|
||||||
newCallback.onClick(SwingSystemTray.this);
|
newCallback.onClick(SwingSystemTray.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -224,7 +239,8 @@ public class SwingSystemTray extends dorkbox.util.tray.SystemTray {
|
|||||||
});
|
});
|
||||||
menuEntry.setText(newMenuText);
|
menuEntry.setText(newMenuText);
|
||||||
menuEntry.revalidate();
|
menuEntry.revalidate();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
addMenuEntry(origMenuText, newCallback);
|
addMenuEntry(origMenuText, newCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user