From 27fa213fc1e3e15226ae34ada8f40d1c7ea68a22 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 26 Sep 2016 23:39:17 +0200 Subject: [PATCH] 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 --- .../systemTray/linux/AppIndicatorTray.java | 13 +-- .../systemTray/linux/GtkSystemTray.java | 10 ++- .../systemTray/linux/GtkTypeSystemTray.java | 45 +--------- src/dorkbox/systemTray/linux/jna/Gobject.java | 2 +- src/dorkbox/systemTray/linux/jna/Gtk.java | 84 ++++++++++++++++++- 5 files changed, 99 insertions(+), 55 deletions(-) diff --git a/src/dorkbox/systemTray/linux/AppIndicatorTray.java b/src/dorkbox/systemTray/linux/AppIndicatorTray.java index 80fe11e..5b68af8 100644 --- a/src/dorkbox/systemTray/linux/AppIndicatorTray.java +++ b/src/dorkbox/systemTray/linux/AppIndicatorTray.java @@ -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 diff --git a/src/dorkbox/systemTray/linux/GtkSystemTray.java b/src/dorkbox/systemTray/linux/GtkSystemTray.java index 9c309ff..3b3dee5 100644 --- a/src/dorkbox/systemTray/linux/GtkSystemTray.java +++ b/src/dorkbox/systemTray/linux/GtkSystemTray.java @@ -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() { diff --git a/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java b/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java index 718aae3..3b1130d 100644 --- a/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java +++ b/src/dorkbox/systemTray/linux/GtkTypeSystemTray.java @@ -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); } } diff --git a/src/dorkbox/systemTray/linux/jna/Gobject.java b/src/dorkbox/systemTray/linux/jna/Gobject.java index da4e89b..1eab6a7 100644 --- a/src/dorkbox/systemTray/linux/jna/Gobject.java +++ b/src/dorkbox/systemTray/linux/jna/Gobject.java @@ -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); diff --git a/src/dorkbox/systemTray/linux/jna/Gtk.java b/src/dorkbox/systemTray/linux/jna/Gtk.java index 783ce4c..e7ab7ac 100644 --- a/src/dorkbox/systemTray/linux/jna/Gtk.java +++ b/src/dorkbox/systemTray/linux/jna/Gtk.java @@ -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); } } }