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 public
AppIndicatorTray() { AppIndicatorTray() {
super();
if (SystemTray.FORCE_TRAY_TYPE == SystemTray.TYPE_GTK_STATUSICON) { if (SystemTray.FORCE_TRAY_TYPE == SystemTray.TYPE_GTK_STATUSICON) {
// if we force GTK type system tray, don't attempt to load AppIndicator libs // 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(); Gtk.startGui();
dispatch(new Runnable() { dispatch(new Runnable() {
@Override @Override
public public
void run() { 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(); Gtk.waitForStartup();
ImageUtils.determineIconSize(SystemTray.TYPE_APP_INDICATOR);
} }
@Override @Override

View File

@ -53,6 +53,12 @@ class GtkSystemTray extends GtkTypeSystemTray {
public public
GtkSystemTray() { GtkSystemTray() {
super(); 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(); Gtk.startGui();
dispatch(new Runnable() { dispatch(new Runnable() {
@ -81,9 +87,7 @@ class GtkSystemTray extends GtkTypeSystemTray {
} }
}); });
super.waitForStartup(); Gtk.waitForStartup();
ImageUtils.determineIconSize(SystemTray.TYPE_GTK_STATUSICON);
// we have to be able to set our title, otherwise the gnome-shell extension WILL NOT work // we have to be able to set our title, otherwise the gnome-shell extension WILL NOT work
dispatch(new Runnable() { dispatch(new Runnable() {

View File

@ -19,8 +19,6 @@ package dorkbox.systemTray.linux;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
@ -29,7 +27,6 @@ import dorkbox.systemTray.SystemTrayMenuAction;
import dorkbox.systemTray.linux.jna.Gobject; import dorkbox.systemTray.linux.jna.Gobject;
import dorkbox.systemTray.linux.jna.Gtk; import dorkbox.systemTray.linux.jna.Gtk;
import dorkbox.systemTray.util.ImageUtils; import dorkbox.systemTray.util.ImageUtils;
import dorkbox.systemTray.util.JavaFX;
/** /**
* Derived from * Derived from
@ -48,45 +45,6 @@ class GtkTypeSystemTray extends SystemTray {
Gtk.dispatch(runnable); 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 @Override
public public
void shutdown() { void shutdown() {
@ -306,7 +264,8 @@ class GtkTypeSystemTray extends SystemTray {
addMenuEntry_(menuText, null, callback); addMenuEntry_(menuText, null, callback);
} }
else { 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_free(Pointer object);
public static native void g_object_unref(Pointer object); public static native void g_object_unref(Pointer object);

View File

@ -16,7 +16,7 @@
package dorkbox.systemTray.linux.jna; package dorkbox.systemTray.linux.jna;
import static dorkbox.systemTray.SystemTray.logger; 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.LinkedList;
import java.util.concurrent.CountDownLatch; 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. * 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 gtkCallbacks.offer(callback); // prevent GC from collecting this object before it can be called
} }
// the correct way to do it // the correct way to do it. Add with a slightly higher value
g_idle_add(callback, null); g_idle_add_full(100, callback, null, null);
} }
} }
} }