From f426e2d08db976900dfc91852484298364bcf356 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 29 Dec 2016 22:55:33 +0100 Subject: [PATCH] Fixed errors with GObject access on FreeBSD + Gnome3. Added text to warning logs. --- src/dorkbox/systemTray/SystemTray.java | 18 +++++++++++------- src/dorkbox/systemTray/jna/linux/Gobject.java | 15 ++++++++++++--- .../systemTray/nativeUI/GtkMenuItem.java | 6 +----- .../nativeUI/GtkMenuItemCheckbox.java | 6 +----- .../nativeUI/_GtkStatusIconNativeTray.java | 17 +++++------------ .../systemTray/swingUI/_AppIndicatorTray.java | 5 +---- .../systemTray/swingUI/_GtkStatusIconTray.java | 16 ++++------------ 7 files changed, 35 insertions(+), 48 deletions(-) diff --git a/src/dorkbox/systemTray/SystemTray.java b/src/dorkbox/systemTray/SystemTray.java index 8a5decd..d0559bb 100644 --- a/src/dorkbox/systemTray/SystemTray.java +++ b/src/dorkbox/systemTray/SystemTray.java @@ -323,7 +323,7 @@ class SystemTray { FORCE_TRAY_TYPE = TrayType.AutoDetect; } } - else if (OS.isLinux()) { + else if (OS.isLinux() || OS.isUnix()) { // kablooie if SWT/JavaFX is not configured in a way that works with us. if (FORCE_TRAY_TYPE != TrayType.Swing) { if (isSwtLoaded) { @@ -419,7 +419,7 @@ class SystemTray { // macosx doesn't respond to all buttons (but should) SystemTrayFixes.fixMacOS(); } - else if (OS.isLinux() && FORCE_TRAY_TYPE != TrayType.Swing) { + else if ((OS.isLinux() || OS.isUnix()) && FORCE_TRAY_TYPE != TrayType.Swing) { // see: https://askubuntu.com/questions/72549/how-to-determine-which-window-manager-is-running // For funsies, SyncThing did a LOT of work on compatibility (unfortunate for us) in python. @@ -446,7 +446,7 @@ class SystemTray { // BLEH. if gnome-shell is running, IT'S REALLY GNOME! // we must ALWAYS do this check!! - boolean isReallyGnome = OSUtil.Linux.DesktopEnv.isGnome(); + boolean isReallyGnome = OSUtil.DesktopEnv.isGnome(); if (isReallyGnome) { if (DEBUG) { @@ -536,7 +536,11 @@ class SystemTray { else if (OSUtil.Linux.isUbuntu()) { // so far, because of the interaction between gnome3 + ubuntu, the GtkStatusIcon miraculously works. trayType = selectTypeQuietly(useNativeMenus, TrayType.GtkStatusIcon); - } else { + } + else if (OSUtil.Unix.isFreeBSD()) { + trayType = selectTypeQuietly(useNativeMenus, TrayType.GtkStatusIcon); + } + else { // arch likely will have problems unless the correct/appropriate libraries are installed. trayType = selectTypeQuietly(useNativeMenus, TrayType.AppIndicator); } @@ -690,7 +694,7 @@ class SystemTray { CacheUtil.tempDir = "SysTray"; try { - if (OS.isLinux()) { + if (OS.isLinux() || OS.isUnix()) { // NOTE: appindicator1 -> GTk2, appindicator3 -> GTK3. // appindicator3 doesn't support menu icons via GTK2!! if (!Gtk.isLoaded) { @@ -752,8 +756,8 @@ class SystemTray { if (!AppIndicator.isLoaded) { // YIKES. Try to fallback to GtkStatusIndicator, since AppIndicator couldn't load. + logger.warn("Unable to initialize the AppIndicator correctly, falling back to GtkStatusIcon type"); trayType = selectTypeQuietly(useNativeMenus, TrayType.GtkStatusIcon); - logger.warn("Unable to initialize the AppIndicator correctly, falling back to GtkStatusIcon."); } } } @@ -794,7 +798,7 @@ class SystemTray { // if it's linux + native menus must not start on the EDT! // _AwtTray must be constructed on the EDT however... if (isJavaFxLoaded || isSwtLoaded || - (OS.isLinux() && NativeUI.class.isAssignableFrom(trayType) && trayType != _AwtTray.class)) { + ((OS.isLinux() || OS.isUnix()) && NativeUI.class.isAssignableFrom(trayType) && trayType != _AwtTray.class)) { try { reference.set((Tray) trayType.getConstructors()[0].newInstance(systemTray)); logger.info("Successfully Loaded: {}", trayType.getSimpleName()); diff --git a/src/dorkbox/systemTray/jna/linux/Gobject.java b/src/dorkbox/systemTray/jna/linux/Gobject.java index 9ce1871..413e45e 100644 --- a/src/dorkbox/systemTray/jna/linux/Gobject.java +++ b/src/dorkbox/systemTray/jna/linux/Gobject.java @@ -15,8 +15,10 @@ */ package dorkbox.systemTray.jna.linux; +import static dorkbox.systemTray.SystemTray.logger; + import com.sun.jna.Callback; -import com.sun.jna.NativeLong; +import com.sun.jna.NativeLibrary; import com.sun.jna.Pointer; import com.sun.jna.ptr.PointerByReference; @@ -31,7 +33,14 @@ public class Gobject { static { - JnaHelper.register("gobject-2.0", Gobject.class); + try { + NativeLibrary library = JnaHelper.register("gobject-2.0", Gobject.class); + if (library == null) { + logger.error("Error loading GObject library, it failed to load."); + } + } catch (Throwable e) { + logger.error("Error loading GObject library, it failed to load {}", e.getMessage()); + } } @@ -42,5 +51,5 @@ class Gobject { public static native void g_object_force_floating(Pointer object); public static native void g_object_ref_sink(Pointer object); - public static native NativeLong g_signal_connect_object(Pointer instance, String detailed_signal, Callback c_handler, Pointer object, int connect_flags); + public static native void g_signal_connect_object(Pointer instance, String detailed_signal, Callback c_handler, Pointer object, int connect_flags); } diff --git a/src/dorkbox/systemTray/nativeUI/GtkMenuItem.java b/src/dorkbox/systemTray/nativeUI/GtkMenuItem.java index 5ed9b75..8c5229c 100644 --- a/src/dorkbox/systemTray/nativeUI/GtkMenuItem.java +++ b/src/dorkbox/systemTray/nativeUI/GtkMenuItem.java @@ -17,7 +17,6 @@ package dorkbox.systemTray.nativeUI; import java.awt.event.ActionListener; -import com.sun.jna.NativeLong; import com.sun.jna.Pointer; import dorkbox.systemTray.MenuItem; @@ -28,9 +27,6 @@ import dorkbox.systemTray.jna.linux.Gtk; import dorkbox.systemTray.peer.MenuItemPeer; class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback { - @SuppressWarnings({"FieldCanBeLocal", "unused"}) - private final NativeLong nativeLong; - private final GtkMenu parent; // these have to be volatile, because they can be changed from any thread @@ -50,7 +46,7 @@ class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback { super(Gtk.gtk_image_menu_item_new_with_mnemonic("")); this.parent = parent; - nativeLong = Gobject.g_signal_connect_object(_native, "activate", this, null, 0); + Gobject.g_signal_connect_object(_native, "activate", this, null, 0); } diff --git a/src/dorkbox/systemTray/nativeUI/GtkMenuItemCheckbox.java b/src/dorkbox/systemTray/nativeUI/GtkMenuItemCheckbox.java index 634feb5..6df2bcf 100644 --- a/src/dorkbox/systemTray/nativeUI/GtkMenuItemCheckbox.java +++ b/src/dorkbox/systemTray/nativeUI/GtkMenuItemCheckbox.java @@ -18,7 +18,6 @@ package dorkbox.systemTray.nativeUI; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import com.sun.jna.NativeLong; import com.sun.jna.Pointer; import dorkbox.systemTray.Checkbox; @@ -30,9 +29,6 @@ import dorkbox.systemTray.peer.CheckboxPeer; // ElementaryOS shows the checkbox on the right, everyone else is on the left. With eOS, we CANNOT show the spacer image. It does not work class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCallback { - @SuppressWarnings({"FieldCanBeLocal", "unused"}) - private final NativeLong nativeLong; - private final GtkMenu parent; // these have to be volatile, because they can be changed from any thread @@ -53,7 +49,7 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall super(Gtk.gtk_check_menu_item_new_with_mnemonic("")); this.parent = parent; - nativeLong = Gobject.g_signal_connect_object(_native, "activate", this, null, 0); + Gobject.g_signal_connect_object(_native, "activate", this, null, 0); } // called by native code diff --git a/src/dorkbox/systemTray/nativeUI/_GtkStatusIconNativeTray.java b/src/dorkbox/systemTray/nativeUI/_GtkStatusIconNativeTray.java index c8ade47..8c0f8ca 100644 --- a/src/dorkbox/systemTray/nativeUI/_GtkStatusIconNativeTray.java +++ b/src/dorkbox/systemTray/nativeUI/_GtkStatusIconNativeTray.java @@ -16,11 +16,8 @@ package dorkbox.systemTray.nativeUI; import java.io.File; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; -import com.sun.jna.NativeLong; import com.sun.jna.Pointer; import dorkbox.systemTray.MenuItem; @@ -45,7 +42,8 @@ class _GtkStatusIconNativeTray extends Tray implements NativeUI { // https://github.com/djdeath/glib/blob/master/gobject/gobject.c // have to save these in a field to prevent GC on the objects (since they go out-of-scope from java) - private final List gtkCallbacks = new ArrayList(); + // see: https://github.com/java-native-access/jna/blob/master/www/CallbacksAndClosures.md + private GEventCallback gtkCallback = null; // This is required if we have JavaFX or SWT shutdown hooks (to prevent us from shutting down twice...) private AtomicBoolean shuttingDown = new AtomicBoolean(); @@ -135,7 +133,7 @@ class _GtkStatusIconNativeTray extends Tray implements NativeUI { // mark for GC trayIcon = null; - gtkCallbacks.clear(); + gtkCallback = null; } }); @@ -153,7 +151,7 @@ class _GtkStatusIconNativeTray extends Tray implements NativeUI { void run() { trayIcon = Gtk.gtk_status_icon_new(); - final GEventCallback gtkCallback = new GEventCallback() { + gtkCallback = new GEventCallback() { @Override public void callback(Pointer notUsed, final GdkEventButton event) { @@ -165,12 +163,7 @@ class _GtkStatusIconNativeTray extends Tray implements NativeUI { } } }; - final NativeLong button_press_event = Gobject.g_signal_connect_object(trayIcon, "button_press_event", - gtkCallback, null, 0); - - // have to do this to prevent GC on these objects - gtkCallbacks.add(gtkCallback); - gtkCallbacks.add(button_press_event); + Gobject.g_signal_connect_object(trayIcon, "button_press_event", gtkCallback, null, 0); } }); diff --git a/src/dorkbox/systemTray/swingUI/_AppIndicatorTray.java b/src/dorkbox/systemTray/swingUI/_AppIndicatorTray.java index afede8e..272a9a1 100644 --- a/src/dorkbox/systemTray/swingUI/_AppIndicatorTray.java +++ b/src/dorkbox/systemTray/swingUI/_AppIndicatorTray.java @@ -20,7 +20,6 @@ import java.awt.Point; import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; -import com.sun.jna.NativeLong; import com.sun.jna.Pointer; import com.sun.jna.ptr.PointerByReference; @@ -92,8 +91,6 @@ class _AppIndicatorTray extends Tray implements SwingUI { private AtomicBoolean shuttingDown = new AtomicBoolean(); // necessary to prevent GC on these objects - @SuppressWarnings({"FieldCanBeLocal", "unused"}) - private NativeLong nativeLong; @SuppressWarnings("FieldCanBeLocal") private GEventCallback gtkCallback; @@ -295,7 +292,7 @@ class _AppIndicatorTray extends Tray implements SwingUI { } }; - nativeLong = Gobject.g_signal_connect_object(rootMenuItem.getValue(), "about-to-show", gtkCallback, null, 0); + Gobject.g_signal_connect_object(rootMenuItem.getValue(), "about-to-show", gtkCallback, null, 0); } private diff --git a/src/dorkbox/systemTray/swingUI/_GtkStatusIconTray.java b/src/dorkbox/systemTray/swingUI/_GtkStatusIconTray.java index d73b8a5..4f2cc5b 100644 --- a/src/dorkbox/systemTray/swingUI/_GtkStatusIconTray.java +++ b/src/dorkbox/systemTray/swingUI/_GtkStatusIconTray.java @@ -18,13 +18,10 @@ package dorkbox.systemTray.swingUI; import java.awt.MouseInfo; import java.awt.Point; import java.io.File; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JPopupMenu; -import com.sun.jna.NativeLong; import com.sun.jna.Pointer; import dorkbox.systemTray.MenuItem; @@ -51,7 +48,8 @@ class _GtkStatusIconTray extends Tray implements SwingUI { private volatile Pointer trayIcon; // have to save these in a field to prevent GC on the objects (since they go out-of-scope from java) - private final List gtkCallbacks = new ArrayList(); + // see: https://github.com/java-native-access/jna/blob/master/www/CallbacksAndClosures.md + private GEventCallback gtkCallback = null; private AtomicBoolean shuttingDown = new AtomicBoolean(); @@ -75,7 +73,7 @@ class _GtkStatusIconTray extends Tray implements SwingUI { void run() { trayIcon = Gtk.gtk_status_icon_new(); - final GEventCallback gtkCallback = new GEventCallback() { + gtkCallback = new GEventCallback() { @Override public void callback(Pointer notUsed, final GdkEventButton event) { @@ -87,12 +85,7 @@ class _GtkStatusIconTray extends Tray implements SwingUI { } } }; - final NativeLong button_press_event = Gobject.g_signal_connect_object(trayIcon, "button_press_event", - gtkCallback, null, 0); - - // have to do this to prevent GC on these objects - gtkCallbacks.add(gtkCallback); - gtkCallbacks.add(button_press_event); + Gobject.g_signal_connect_object(trayIcon, "button_press_event", gtkCallback, null, 0); } }); @@ -209,7 +202,6 @@ class _GtkStatusIconTray extends Tray implements SwingUI { // mark for GC trayIcon = null; - gtkCallbacks.clear(); } });