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;
|
static volatile boolean isVersion3 = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is AppIndicator loaded yet?
|
||||||
|
*/
|
||||||
|
static volatile boolean isLoaded = false;
|
||||||
|
|
||||||
|
|
||||||
public static
|
public static
|
||||||
AppIndicator get() {
|
AppIndicator get() {
|
||||||
Object library;
|
Object library;
|
||||||
|
|
||||||
|
// NOTE: GtkSupport uses this info to figure out WHAT VERSION OF GTK to use: appindiactor1 -> GTk2, appindicator3 -> GTK3.
|
||||||
|
|
||||||
// start with base version
|
// start with base version
|
||||||
try {
|
try {
|
||||||
library = Native.loadLibrary("appindicator", AppIndicator.class);
|
library = Native.loadLibrary("appindicator3", AppIndicator.class);
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
|
String s = library.toString();
|
||||||
|
if (s.indexOf("appindicator3") > 0) {
|
||||||
|
isVersion3 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoaded = true;
|
||||||
return (AppIndicator) library;
|
return (AppIndicator) library;
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
@ -17,7 +17,6 @@ package dorkbox.util.jna.linux;
|
|||||||
|
|
||||||
import com.sun.jna.Function;
|
import com.sun.jna.Function;
|
||||||
import com.sun.jna.Library;
|
import com.sun.jna.Library;
|
||||||
import com.sun.jna.Native;
|
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
import com.sun.jna.Structure;
|
import com.sun.jna.Structure;
|
||||||
import dorkbox.util.Keep;
|
import dorkbox.util.Keep;
|
||||||
@ -25,15 +24,17 @@ import dorkbox.util.Keep;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface Gtk extends Library {
|
public
|
||||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep image
|
interface Gtk extends Library {
|
||||||
Gtk INSTANCE = (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
|
||||||
|
// 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 FALSE = 0;
|
||||||
int TRUE = 1;
|
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
|
@Keep
|
||||||
class GdkEventButton extends Structure {
|
class GdkEventButton extends Structure {
|
||||||
@ -51,43 +52,36 @@ public interface Gtk extends Library {
|
|||||||
public double y_root;
|
public double y_root;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<String> getFieldOrder() {
|
protected
|
||||||
return Arrays.asList("type",
|
List<String> getFieldOrder() {
|
||||||
"window",
|
return Arrays.asList("type", "window", "send_event", "time", "x", "y", "axes", "state", "button", "device", "x_root", "y_root");
|
||||||
"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);
|
void gtk_init(int argc, String[] argv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the main loop until gtk_main_quit() is called.
|
* 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
|
||||||
* You can nest calls to gtk_main(). In that case gtk_main_quit() will make the innermost invocation of the main loop return.
|
* innermost invocation of the main loop return.
|
||||||
*/
|
*/
|
||||||
void gtk_main();
|
void gtk_main();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the innermost invocation of the main loop return when it regains control. ONLY CALL FROM THE GtkSupport class, UNLESS
|
* Makes the innermost invocation of the main loop return when it regains control. ONLY CALL FROM THE GtkSupport class, UNLESS you know
|
||||||
* you know what you're doing!
|
* what you're doing!
|
||||||
*/
|
*/
|
||||||
void gtk_main_quit();
|
void gtk_main_quit();
|
||||||
|
|
||||||
void gdk_threads_init();
|
void gdk_threads_init();
|
||||||
|
|
||||||
void gdk_threads_enter();
|
void gdk_threads_enter();
|
||||||
|
|
||||||
void gdk_threads_leave();
|
void gdk_threads_leave();
|
||||||
|
|
||||||
Pointer gtk_menu_new();
|
Pointer gtk_menu_new();
|
||||||
|
|
||||||
Pointer gtk_menu_item_new();
|
Pointer gtk_menu_item_new();
|
||||||
|
|
||||||
Pointer gtk_menu_item_new_with_label(String label);
|
Pointer gtk_menu_item_new_with_label(String label);
|
||||||
|
|
||||||
// to create a menu entry WITH an icon.
|
// 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);
|
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_image(Pointer image_menu_item, Pointer image);
|
||||||
|
|
||||||
void gtk_image_menu_item_set_always_show_image(Pointer menu_item, int forceShow);
|
void gtk_image_menu_item_set_always_show_image(Pointer menu_item, int forceShow);
|
||||||
|
|
||||||
Pointer gtk_bin_get_child(Pointer parent);
|
Pointer gtk_bin_get_child(Pointer parent);
|
||||||
|
|
||||||
void gtk_label_set_text(Pointer label, String text);
|
void gtk_label_set_text(Pointer label, String text);
|
||||||
|
|
||||||
void gtk_label_set_markup(Pointer label, Pointer markup);
|
void gtk_label_set_markup(Pointer label, Pointer markup);
|
||||||
|
|
||||||
void gtk_label_set_use_markup(Pointer label, int gboolean);
|
void gtk_label_set_use_markup(Pointer label, int gboolean);
|
||||||
|
|
||||||
Pointer gtk_status_icon_new();
|
Pointer gtk_status_icon_new();
|
||||||
|
|
||||||
void gtk_status_icon_set_from_file(Pointer widget, String lablel);
|
void gtk_status_icon_set_from_file(Pointer widget, String lablel);
|
||||||
|
|
||||||
void gtk_status_icon_set_visible(Pointer widget, boolean visible);
|
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_tooltip(Pointer widget, String tooltipText);
|
||||||
|
|
||||||
void gtk_status_icon_set_title(Pointer widget, String titleText);
|
void gtk_status_icon_set_title(Pointer widget, String titleText);
|
||||||
|
|
||||||
void gtk_status_icon_set_name(Pointer widget, String name);
|
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_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_item_set_label(Pointer menu_item, String label);
|
||||||
|
|
||||||
void gtk_menu_shell_append(Pointer menu_shell, Pointer child);
|
void gtk_menu_shell_append(Pointer menu_shell, Pointer child);
|
||||||
|
|
||||||
void gtk_menu_shell_deactivate(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_widget_set_sensitive(Pointer widget, int sensitive);
|
||||||
|
|
||||||
void gtk_container_remove(Pointer menu, Pointer subItem);
|
void gtk_container_remove(Pointer menu, Pointer subItem);
|
||||||
|
|
||||||
void gtk_widget_show(Pointer widget);
|
void gtk_widget_show(Pointer widget);
|
||||||
|
|
||||||
void gtk_widget_show_all(Pointer widget);
|
void gtk_widget_show_all(Pointer widget);
|
||||||
|
|
||||||
void gtk_widget_destroy(Pointer widget);
|
void gtk_widget_destroy(Pointer widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.jna.linux;
|
package dorkbox.util.jna.linux;
|
||||||
|
|
||||||
|
import com.sun.jna.Function;
|
||||||
|
import com.sun.jna.Native;
|
||||||
import dorkbox.util.Property;
|
import dorkbox.util.Property;
|
||||||
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
@ -22,8 +24,6 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
|
|
||||||
public
|
public
|
||||||
class GtkSupport {
|
class GtkSupport {
|
||||||
public static final boolean isSupported;
|
|
||||||
|
|
||||||
// RE: SWT
|
// RE: SWT
|
||||||
// https://developer.gnome.org/glib/stable/glib-Deprecated-Thread-APIs.html#g-thread-init
|
// 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()
|
// 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. */
|
/** 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;
|
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 {
|
try {
|
||||||
if (Gtk.INSTANCE != null && Gobject.INSTANCE != null && GThread.INSTANCE != null) {
|
gtk_status_icon_position_menu = Function.getFunction("libgtk-3.so.0", "gtk_status_icon_position_menu");
|
||||||
hasSupport = true;
|
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) {
|
} 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
|
public static
|
||||||
|
Loading…
Reference in New Issue
Block a user