Added GTK3 support (now libappindicator3 works correctly with regards to showing menu icons).Moved all GTK operations to a single thread. Moved error logs from System.err -> logger. Made SystemTray a singleton (it will no longer have the java-side get accidentally garbage collected).
This commit is contained in:
parent
9081643963
commit
176f64fd6e
|
@ -29,15 +29,28 @@ class AppIndicatorQuery {
|
|||
*/
|
||||
static volatile boolean isVersion3 = false;
|
||||
|
||||
/**
|
||||
* Is AppIndicator loaded yet?
|
||||
*/
|
||||
static volatile boolean isLoaded = false;
|
||||
|
||||
|
||||
public static
|
||||
AppIndicator get() {
|
||||
Object library;
|
||||
|
||||
// NOTE: GtkSupport uses this info to figure out WHAT VERSION OF GTK to use: appindiactor1 -> GTk2, appindicator3 -> GTK3.
|
||||
|
||||
// start with base version
|
||||
try {
|
||||
library = Native.loadLibrary("appindicator", AppIndicator.class);
|
||||
library = Native.loadLibrary("appindicator3", AppIndicator.class);
|
||||
if (library != null) {
|
||||
String s = library.toString();
|
||||
if (s.indexOf("appindicator3") > 0) {
|
||||
isVersion3 = true;
|
||||
}
|
||||
|
||||
isLoaded = true;
|
||||
return (AppIndicator) library;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
|
|
|
@ -17,7 +17,6 @@ package dorkbox.util.jna.linux;
|
|||
|
||||
import com.sun.jna.Function;
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import dorkbox.util.Keep;
|
||||
|
@ -25,15 +24,17 @@ import dorkbox.util.Keep;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface Gtk extends Library {
|
||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep image
|
||||
Gtk INSTANCE = (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
||||
public
|
||||
interface Gtk extends Library {
|
||||
|
||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep gtk
|
||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 | grep gtk
|
||||
Gtk INSTANCE = GtkSupport.get();
|
||||
Function gtk_status_icon_position_menu = GtkSupport.gtk_status_icon_position_menu;
|
||||
|
||||
int FALSE = 0;
|
||||
int TRUE = 1;
|
||||
|
||||
void gtk_box_pack_start(Pointer box, Pointer child, int expand, int fill, int padding);
|
||||
void gtk_box_pack_end(Pointer box, Pointer child, int expand, int fill, int padding);
|
||||
|
||||
@Keep
|
||||
class GdkEventButton extends Structure {
|
||||
|
@ -51,43 +52,36 @@ public interface Gtk extends Library {
|
|||
public double y_root;
|
||||
|
||||
@Override
|
||||
protected List<String> getFieldOrder() {
|
||||
return Arrays.asList("type",
|
||||
"window",
|
||||
"send_event",
|
||||
"time",
|
||||
"x",
|
||||
"y",
|
||||
"axes",
|
||||
"state",
|
||||
"button",
|
||||
"device",
|
||||
"x_root",
|
||||
"y_root");
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("type", "window", "send_event", "time", "x", "y", "axes", "state", "button", "device", "x_root", "y_root");
|
||||
}
|
||||
}
|
||||
|
||||
Function gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
||||
|
||||
void gtk_init(int argc, String[] argv);
|
||||
|
||||
/**
|
||||
* Runs the main loop until gtk_main_quit() is called.
|
||||
* You can nest calls to gtk_main(). In that case gtk_main_quit() will make the innermost invocation of the main loop return.
|
||||
* Runs the main loop until gtk_main_quit() is called. You can nest calls to gtk_main(). In that case gtk_main_quit() will make the
|
||||
* innermost invocation of the main loop return.
|
||||
*/
|
||||
void gtk_main();
|
||||
|
||||
/**
|
||||
* Makes the innermost invocation of the main loop return when it regains control. ONLY CALL FROM THE GtkSupport class, UNLESS
|
||||
* you know what you're doing!
|
||||
* Makes the innermost invocation of the main loop return when it regains control. ONLY CALL FROM THE GtkSupport class, UNLESS you know
|
||||
* what you're doing!
|
||||
*/
|
||||
void gtk_main_quit();
|
||||
|
||||
void gdk_threads_init();
|
||||
|
||||
void gdk_threads_enter();
|
||||
|
||||
void gdk_threads_leave();
|
||||
|
||||
Pointer gtk_menu_new();
|
||||
|
||||
Pointer gtk_menu_item_new();
|
||||
|
||||
Pointer gtk_menu_item_new_with_label(String label);
|
||||
|
||||
// to create a menu entry WITH an icon.
|
||||
|
@ -95,15 +89,21 @@ public interface Gtk extends Library {
|
|||
|
||||
|
||||
Pointer gtk_image_menu_item_new_with_label(String label);
|
||||
|
||||
void gtk_image_menu_item_set_image(Pointer image_menu_item, Pointer image);
|
||||
|
||||
void gtk_image_menu_item_set_always_show_image(Pointer menu_item, int forceShow);
|
||||
|
||||
Pointer gtk_bin_get_child(Pointer parent);
|
||||
|
||||
void gtk_label_set_text(Pointer label, String text);
|
||||
|
||||
void gtk_label_set_markup(Pointer label, Pointer markup);
|
||||
|
||||
void gtk_label_set_use_markup(Pointer label, int gboolean);
|
||||
|
||||
Pointer gtk_status_icon_new();
|
||||
|
||||
void gtk_status_icon_set_from_file(Pointer widget, String lablel);
|
||||
|
||||
void gtk_status_icon_set_visible(Pointer widget, boolean visible);
|
||||
|
@ -112,19 +112,25 @@ public interface Gtk extends Library {
|
|||
// void gtk_status_icon_set_tooltip(Pointer widget, String tooltipText);
|
||||
|
||||
void gtk_status_icon_set_title(Pointer widget, String titleText);
|
||||
|
||||
void gtk_status_icon_set_name(Pointer widget, String name);
|
||||
|
||||
void gtk_menu_popup(Pointer menu, Pointer widget, Pointer bla, Function func, Pointer data, int button, int time);
|
||||
|
||||
void gtk_menu_item_set_label(Pointer menu_item, String label);
|
||||
|
||||
void gtk_menu_shell_append(Pointer menu_shell, Pointer child);
|
||||
|
||||
void gtk_menu_shell_deactivate(Pointer menu_shell, Pointer child);
|
||||
|
||||
void gtk_widget_set_sensitive(Pointer widget, int sensitive);
|
||||
|
||||
void gtk_container_remove(Pointer menu, Pointer subItem);
|
||||
|
||||
void gtk_widget_show(Pointer widget);
|
||||
|
||||
void gtk_widget_show_all(Pointer widget);
|
||||
|
||||
void gtk_widget_destroy(Pointer widget);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package dorkbox.util.jna.linux;
|
||||
|
||||
import com.sun.jna.Function;
|
||||
import com.sun.jna.Native;
|
||||
import dorkbox.util.Property;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
@ -22,8 +24,6 @@ import java.util.concurrent.CountDownLatch;
|
|||
|
||||
public
|
||||
class GtkSupport {
|
||||
public static final boolean isSupported;
|
||||
|
||||
// RE: SWT
|
||||
// https://developer.gnome.org/glib/stable/glib-Deprecated-Thread-APIs.html#g-thread-init
|
||||
// Since version >= 2.24, threads can only init once. Multiple calls do nothing, and we can nest gtk_main()
|
||||
|
@ -37,16 +37,71 @@ class GtkSupport {
|
|||
/** Enables/Disables the creation of a native GTK event loop. Useful if you are already creating one via SWT/etc. */
|
||||
public static boolean CREATE_EVENT_LOOP = true;
|
||||
|
||||
static {
|
||||
boolean hasSupport = false;
|
||||
/**
|
||||
* must call get() before accessing this! Only "Gtk" interface should access this!
|
||||
*/
|
||||
static volatile Function gtk_status_icon_position_menu = null;
|
||||
|
||||
public static volatile boolean isGtk2 = false;
|
||||
|
||||
/**
|
||||
* Helper for GTK, because we could have v3 or v2
|
||||
*/
|
||||
@SuppressWarnings("Duplicates")
|
||||
public static
|
||||
Gtk get() {
|
||||
Object library;
|
||||
|
||||
if (AppIndicatorQuery.isLoaded) {
|
||||
if (AppIndicatorQuery.isVersion3) {
|
||||
// appindicator3 requires GTK3
|
||||
try {
|
||||
if (Gtk.INSTANCE != null && Gobject.INSTANCE != null && GThread.INSTANCE != null) {
|
||||
hasSupport = true;
|
||||
gtk_status_icon_position_menu = Function.getFunction("libgtk-3.so.0", "gtk_status_icon_position_menu");
|
||||
library = Native.loadLibrary("libgtk-3.so.0", Gtk.class);
|
||||
if (library != null) {
|
||||
return (Gtk) library;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
} else {
|
||||
// appindicator1 requires GTK2
|
||||
try {
|
||||
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
||||
library = Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
||||
if (library != null) {
|
||||
isGtk2 = true;
|
||||
return (Gtk) library;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now for the defaults...
|
||||
|
||||
// start with version 3
|
||||
try {
|
||||
gtk_status_icon_position_menu = Function.getFunction("libgtk-3.so.0", "gtk_status_icon_position_menu");
|
||||
library = Native.loadLibrary("libgtk-3.so.0", Gtk.class);
|
||||
if (library != null) {
|
||||
return (Gtk) library;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
isSupported = hasSupport;
|
||||
// now version 2
|
||||
try {
|
||||
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
||||
library = Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
||||
if (library != null) {
|
||||
isGtk2 = true;
|
||||
return (Gtk) library;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
throw new RuntimeException("We apologize for this, but we are unable to determine the GTK library is in use, if " +
|
||||
"or even if it is in use... Please create an issue for this and include your OS type and configuration.");
|
||||
}
|
||||
|
||||
public static
|
||||
|
|
Loading…
Reference in New Issue
Block a user