Changed to g_idle_add_full, GTK dispatch now waits for a short time +

checks event queue before starting up. AppIndicator now starts up
 with a transparent icon
This commit is contained in:
nathan 2016-09-26 23:39:17 +02:00
parent 77b0fc4691
commit 27fa213fc1
5 changed files with 99 additions and 55 deletions

View File

@ -45,24 +45,27 @@ class AppIndicatorTray extends GtkTypeSystemTray {
public
AppIndicatorTray() {
super();
if (SystemTray.FORCE_TRAY_TYPE == SystemTray.TYPE_GTK_STATUSICON) {
// if we force GTK type system tray, don't attempt to load AppIndicator libs
throw new IllegalArgumentException("Unable to start AppIndicator if 'SystemTray.FORCE_TRAY_TYPE' is set to GTK");
throw new IllegalArgumentException("Unable to start AppIndicator if 'SystemTray.FORCE_TRAY_TYPE' is set to GtkStatusIcon");
}
ImageUtils.determineIconSize(SystemTray.TYPE_APP_INDICATOR);
Gtk.startGui();
dispatch(new Runnable() {
@Override
public
void run() {
appIndicator = AppIndicator.app_indicator_new(System.nanoTime() + "DBST", "", AppIndicator.CATEGORY_APPLICATION_STATUS);
// we initialize with a blank image
File image = ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE);
String id = System.nanoTime() + "DBST";
appIndicator = AppIndicator.app_indicator_new(id, image.getAbsolutePath(), AppIndicator.CATEGORY_APPLICATION_STATUS);
}
});
super.waitForStartup();
ImageUtils.determineIconSize(SystemTray.TYPE_APP_INDICATOR);
Gtk.waitForStartup();
}
@Override

View File

@ -53,6 +53,12 @@ class GtkSystemTray extends GtkTypeSystemTray {
public
GtkSystemTray() {
super();
if (SystemTray.FORCE_TRAY_TYPE == SystemTray.TYPE_APP_INDICATOR) {
// if we force GTK type system tray, don't attempt to load AppIndicator libs
throw new IllegalArgumentException("Unable to start GtkStatusIcon if 'SystemTray.FORCE_TRAY_TYPE' is set to AppIndicator");
}
ImageUtils.determineIconSize(SystemTray.TYPE_GTK_STATUSICON);
Gtk.startGui();
dispatch(new Runnable() {
@ -81,9 +87,7 @@ class GtkSystemTray extends GtkTypeSystemTray {
}
});
super.waitForStartup();
ImageUtils.determineIconSize(SystemTray.TYPE_GTK_STATUSICON);
Gtk.waitForStartup();
// we have to be able to set our title, otherwise the gnome-shell extension WILL NOT work
dispatch(new Runnable() {

View File

@ -19,8 +19,6 @@ package dorkbox.systemTray.linux;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.sun.jna.Pointer;
@ -29,7 +27,6 @@ import dorkbox.systemTray.SystemTrayMenuAction;
import dorkbox.systemTray.linux.jna.Gobject;
import dorkbox.systemTray.linux.jna.Gtk;
import dorkbox.systemTray.util.ImageUtils;
import dorkbox.systemTray.util.JavaFX;
/**
* Derived from
@ -48,45 +45,6 @@ class GtkTypeSystemTray extends SystemTray {
Gtk.dispatch(runnable);
}
protected
void waitForStartup() {
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
Gtk.dispatch(new Runnable() {
@Override
public
void run() {
blockUntilStarted.countDown();
}
});
if (SystemTray.isJavaFxLoaded) {
if (!JavaFX.isEventThread()) {
try {
blockUntilStarted.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else if (SystemTray.isSwtLoaded) {
if (SystemTray.FORCE_TRAY_TYPE != SystemTray.TYPE_GTK_STATUSICON) {
// GTK system tray has threading issues if we block here (because it is likely in the event thread)
// AppIndicator version doesn't have this problem
try {
blockUntilStarted.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
try {
blockUntilStarted.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public
void shutdown() {
@ -306,7 +264,8 @@ class GtkTypeSystemTray extends SystemTray {
addMenuEntry_(menuText, null, callback);
}
else {
addMenuEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl), callback);
// addMenuEntry_(menuText, ImageUtils.resizeAndCache(ImageUtils.ENTRY_SIZE, imageUrl), callback);
addMenuEntry_(menuText, ImageUtils.getTransparentImage(ImageUtils.ENTRY_SIZE), callback);
}
}

View File

@ -32,7 +32,7 @@ class Gobject {
}
public static native void g_idle_add(FuncCallback callback, Pointer data);
public static native int g_idle_add_full(int priority, FuncCallback callback, Pointer data, Pointer notify);
public static native void g_free(Pointer object);
public static native void g_object_unref(Pointer object);

View File

@ -16,7 +16,7 @@
package dorkbox.systemTray.linux.jna;
import static dorkbox.systemTray.SystemTray.logger;
import static dorkbox.systemTray.linux.jna.Gobject.g_idle_add;
import static dorkbox.systemTray.linux.jna.Gobject.g_idle_add_full;
import java.util.LinkedList;
import java.util.concurrent.CountDownLatch;
@ -234,6 +234,84 @@ class Gtk {
}
}
/**
* Waits for the GUI to finish loading
*/
public static
void waitForStartup() {
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
dispatch(new Runnable() {
@Override
public
void run() {
blockUntilStarted.countDown();
}
});
if (SystemTray.isJavaFxLoaded) {
if (!JavaFX.isEventThread()) {
try {
// we have to WAIT until all events are done processing, OTHERWISE we have initialization issues
while (true) {
Thread.sleep(100);
synchronized (gtkCallbacks) {
if (gtkCallbacks.isEmpty()) {
break;
}
}
}
blockUntilStarted.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else if (SystemTray.isSwtLoaded) {
if (SystemTray.FORCE_TRAY_TYPE != SystemTray.TYPE_GTK_STATUSICON) {
// GTK system tray has threading issues if we block here (because it is likely in the event thread)
// AppIndicator version doesn't have this problem
// we have to WAIT until all events are done processing, OTHERWISE we have initialization issues
try {
while (true) {
Thread.sleep(100);
synchronized (gtkCallbacks) {
if (gtkCallbacks.isEmpty()) {
break;
}
}
}
blockUntilStarted.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
try {
// we have to WAIT until all events are done processing, OTHERWISE we have initialization issues
while (true) {
Thread.sleep(100);
synchronized (gtkCallbacks) {
if (gtkCallbacks.isEmpty()) {
break;
}
}
}
blockUntilStarted.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Best practices for GTK, is to call EVERYTHING for it on the GTK THREAD. This accomplishes that.
*/
@ -296,8 +374,8 @@ class Gtk {
gtkCallbacks.offer(callback); // prevent GC from collecting this object before it can be called
}
// the correct way to do it
g_idle_add(callback, null);
// the correct way to do it. Add with a slightly higher value
g_idle_add_full(100, callback, null, null);
}
}
}