Added support for detecting if javaFX already started the GTK event loop (and hooking into the right places for shutdown if it does).

This commit is contained in:
nathan 2016-02-14 12:58:45 +01:00
parent 2aaf41204e
commit 010a91ca68
5 changed files with 195 additions and 6 deletions

View File

@ -133,7 +133,7 @@ This project is **kept in sync** with the utilities library, so "jar hell" is no
<dependency>
<groupId>com.dorkbox</groupId>
<artifactId>SystemTray</artifactId>
<version>2.4</version>
<version>2.8</version>
</dependency>
```

View File

@ -26,6 +26,7 @@
<orderEntry type="module" module-name="Dorkbox-Util" />
<orderEntry type="module" module-name="JavaLauncher-Util" />
<orderEntry type="library" name="jna (4.2.1)" level="application" />
<orderEntry type="library" name="SWT" level="project" />
</component>
<component name="org.twodividedbyzero.idea.findbugs">
<option name="_basePreferences">

View File

@ -34,6 +34,7 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
@ -268,7 +269,34 @@ class SystemTray {
} catch (Exception e) {
logger.error("Unable to create tray type: '" + trayType.getSimpleName() + "'", e);
}
systemTray = systemTray_;
// Necessary because javaFX **ALSO** runs a gtk main loop, and when it stops (if we don't stop first), we become unresponsive.
// If javaFX is present, but not used, this does nothing.
// com.sun.javafx.tk.Toolkit.getToolkit()
// .addShutdownHook(new Runnable() {
// @Override
// public
// void run() {
// systemTray.shutdown();
// }
// });
try {
Class<?> clazz = Class.forName("com.sun.javafx.tk.Toolkit");
Method method = clazz.getMethod("getToolkit");
Object o = method.invoke(null);
Method runnable = o.getClass()
.getMethod("addShutdownHook", Runnable.class);
runnable.invoke(o, new Runnable() {
@Override
public
void run() {
systemTray.shutdown();
}
});
} catch (Throwable ignored) {
}
}
}
@ -277,7 +305,7 @@ class SystemTray {
*/
public static
String getVersion() {
return "2.4";
return "2.8";
}
/**

View File

@ -46,9 +46,9 @@ class TestTray {
new TestTray();
}
private final SystemTray systemTray;
private final SystemTrayMenuAction callbackGreen;
private final SystemTrayMenuAction callbackGray;
private SystemTray systemTray;
private SystemTrayMenuAction callbackGreen;
private SystemTrayMenuAction callbackGray;
public
TestTray() {
@ -119,7 +119,7 @@ class TestTray {
public
void onClick(final SystemTray systemTray, final MenuEntry menuEntry) {
systemTray.shutdown();
//System.exit(0); not necessary if all non-daemon threads have correctly stopped.
//System.exit(0); not necessary if all non-daemon threads have stopped.
}
});
}

View File

@ -0,0 +1,160 @@
/*
* Copyright 2015 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox;
import dorkbox.systemTray.MenuEntry;
import dorkbox.systemTray.SystemTray;
import dorkbox.systemTray.SystemTrayMenuAction;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* Icons from 'SJJB Icons', public domain/CC0 icon set
*
* Needs JavaFX to run
*/
public
class TestTrayJavaFX extends Application {
// horribly hacky. ONLY FOR TESTING!
public static final URL BLACK_MAIL = TestTrayJavaFX.class.getResource("mail.000000.24.png");
public static final URL GREEN_MAIL = TestTrayJavaFX.class.getResource("mail.39AC39.24.png");
public static final URL LT_GRAY_MAIL = TestTrayJavaFX.class.getResource("mail.999999.24.png");
public static
void main(String[] args) {
// ONLY if manually loading JNA jars.
//
// Not necessary if using the official JNA downloaded from https://github.com/twall/jna AND THAT JAR is on the classpath
//
System.load(new File("../../resources/Dependencies/jna/linux_64/libjna.so").getAbsolutePath()); //64bit linux library
launch(TestTrayJavaFX.class);
}
private SystemTray systemTray;
private SystemTrayMenuAction callbackGreen;
private SystemTrayMenuAction callbackGray;
public
TestTrayJavaFX() {
}
@Override
public
void start(final Stage primaryStage) throws Exception {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
this.systemTray = SystemTray.getSystemTray();
if (systemTray == null) {
throw new RuntimeException("Unable to load SystemTray!");
}
try {
this.systemTray.setIcon(LT_GRAY_MAIL);
} catch (IOException e) {
e.printStackTrace();
}
systemTray.setStatus("No Mail");
callbackGreen = new SystemTrayMenuAction() {
@Override
public
void onClick(final SystemTray systemTray, final MenuEntry menuEntry) {
systemTray.setStatus("Some Mail!");
try {
systemTray.setIcon(GREEN_MAIL);
} catch (IOException e) {
e.printStackTrace();
}
menuEntry.setCallback(callbackGray);
try {
menuEntry.setImage(BLACK_MAIL);
} catch (IOException e) {
e.printStackTrace();
}
menuEntry.setText("Delete Mail");
// systemTray.removeMenuEntry(menuEntry);
}
};
callbackGray = new SystemTrayMenuAction() {
@Override
public
void onClick(final SystemTray systemTray, final MenuEntry menuEntry) {
systemTray.setStatus(null);
try {
systemTray.setIcon(BLACK_MAIL);
} catch (IOException e) {
e.printStackTrace();
}
menuEntry.setCallback(null);
// systemTray.setStatus("Mail Empty");
systemTray.removeMenuEntry(menuEntry);
System.err.println("POW");
}
};
try {
this.systemTray.addMenuEntry("Green Mail", GREEN_MAIL, callbackGreen);
} catch (IOException e) {
e.printStackTrace();
}
systemTray.addMenuEntry("Quit", new SystemTrayMenuAction() {
@Override
public
void onClick(final SystemTray systemTray, final MenuEntry menuEntry) {
systemTray.shutdown();
Platform.exit(); // necessary to close javaFx
//System.exit(0); not necessary if all non-daemon threads have stopped.
}
});
}
}