Updated jna to have better support for bad libappindicator libraries

This commit is contained in:
nathan 2015-06-28 12:59:35 +02:00
parent 373a0368a1
commit 43b0c7f4ef
5 changed files with 246 additions and 210 deletions

View File

@ -1,45 +1,46 @@
package dorkbox.util.jna.linux; package dorkbox.util.jna.linux;
import java.util.Arrays; import com.sun.jna.*;
import java.util.List;
import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import dorkbox.util.Keep; import dorkbox.util.Keep;
import dorkbox.util.jna.linux.Gobject.GObjectClassStruct; import dorkbox.util.jna.linux.Gobject.GObjectClassStruct;
import dorkbox.util.jna.linux.Gobject.GObjectStruct; import dorkbox.util.jna.linux.Gobject.GObjectStruct;
import java.util.Arrays;
import java.util.List;
/* bindings for libappindicator 0.1 */ /* bindings for libappindicator 0.1 */
public interface AppIndicator extends Library { public
public static AppIndicator INSTANCE = (AppIndicator) Native.loadLibrary("appindicator", AppIndicator.class); interface AppIndicator extends Library {
AppIndicator INSTANCE = (AppIndicator) Native.loadLibrary("appindicator", AppIndicator.class);
public static final int CATEGORY_APPLICATION_STATUS = 0; int CATEGORY_APPLICATION_STATUS = 0;
public static final int CATEGORY_COMMUNICATIONS = 1; int CATEGORY_COMMUNICATIONS = 1;
public static final int CATEGORY_SYSTEM_SERVICES = 2; int CATEGORY_SYSTEM_SERVICES = 2;
public static final int CATEGORY_HARDWARE = 3; int CATEGORY_HARDWARE = 3;
public static final int CATEGORY_OTHER = 4; int CATEGORY_OTHER = 4;
public static final int STATUS_PASSIVE = 0; int STATUS_PASSIVE = 0;
public static final int STATUS_ACTIVE = 1; int STATUS_ACTIVE = 1;
public static final int STATUS_ATTENTION = 2; int STATUS_ATTENTION = 2;
@dorkbox.util.Keep
public interface Fallback extends Callback {
public Pointer callback(AppIndicatorInstanceStruct self);
}
@Keep @Keep
public interface Unfallback extends Callback { interface Fallback extends Callback {
public void callback(AppIndicatorInstanceStruct self, Pointer status_icon); Pointer callback(AppIndicatorInstanceStruct self);
} }
@Keep @Keep
public class AppIndicatorClassStruct extends Structure { interface Unfallback extends Callback {
public class ByReference extends AppIndicatorClassStruct implements Structure.ByReference {} void callback(AppIndicatorInstanceStruct self, Pointer status_icon);
}
@Keep
class AppIndicatorClassStruct extends Structure {
public
class ByReference extends AppIndicatorClassStruct implements Structure.ByReference {}
public GObjectClassStruct parent_class; public GObjectClassStruct parent_class;
@ -60,75 +61,88 @@ public interface AppIndicator extends Library {
public Pointer app_indicator_reserved_5; public Pointer app_indicator_reserved_5;
public Pointer app_indicator_reserved_6; public Pointer app_indicator_reserved_6;
public AppIndicatorClassStruct() {} public
public AppIndicatorClassStruct(Pointer p) { AppIndicatorClassStruct() {
}
public
AppIndicatorClassStruct(Pointer p) {
super(p); super(p);
useMemory(p); useMemory(p);
read(); read();
} }
@Override @Override
protected List<String> getFieldOrder() { protected
return Arrays.asList("parent_class", List<String> getFieldOrder() {
"new_icon", return Arrays.asList("parent_class", "new_icon", "new_attention_icon", "new_status", "new_icon_theme", "new_label",
"new_attention_icon", "connection_changed", "scroll_event", "app_indicator_reserved_ats", "fallback", "unfallback",
"new_status", "app_indicator_reserved_1", "app_indicator_reserved_2", "app_indicator_reserved_3",
"new_icon_theme", "app_indicator_reserved_4", "app_indicator_reserved_5", "app_indicator_reserved_6");
"new_label",
"connection_changed",
"scroll_event",
"app_indicator_reserved_ats",
"fallback",
"unfallback",
"app_indicator_reserved_1",
"app_indicator_reserved_2",
"app_indicator_reserved_3",
"app_indicator_reserved_4",
"app_indicator_reserved_5",
"app_indicator_reserved_6");
} }
} }
@Keep @Keep
public class AppIndicatorInstanceStruct extends Structure { class AppIndicatorInstanceStruct extends Structure {
public GObjectStruct parent; public GObjectStruct parent;
public Pointer priv; public Pointer priv;
@Override @Override
protected List<String> getFieldOrder() { protected
return Arrays.asList("parent", List<String> getFieldOrder() {
"priv"); return Arrays.asList("parent", "priv");
} }
} }
public AppIndicatorInstanceStruct app_indicator_new(String id, String icon_name, int category); AppIndicatorInstanceStruct app_indicator_new(String id, String icon_name, int category);
public AppIndicatorInstanceStruct app_indicator_new_with_path(String id, String icon_name, int category, String icon_theme_path);
public void app_indicator_set_status(AppIndicatorInstanceStruct self, int status);
public void app_indicator_set_attention_icon(AppIndicatorInstanceStruct self, String icon_name);
public void app_indicator_set_attention_icon_full(AppIndicatorInstanceStruct self, String name, String icon_desc);
public void app_indicator_set_menu(AppIndicatorInstanceStruct self, Pointer menu);
public void app_indicator_set_icon(AppIndicatorInstanceStruct self, String icon_name);
public void app_indicator_set_icon_full(AppIndicatorInstanceStruct self, String icon_name, String icon_desc);
public void app_indicator_set_label(AppIndicatorInstanceStruct self, String label, String guide);
public void app_indicator_set_icon_theme_path(AppIndicatorInstanceStruct self, String icon_theme_path);
public void app_indicator_set_ordering_index(AppIndicatorInstanceStruct self, int ordering_index);
public void app_indicator_set_secondary_active_target(AppIndicatorInstanceStruct self, Pointer menuitem);
public String app_indicator_get_id(AppIndicatorInstanceStruct self); AppIndicatorInstanceStruct app_indicator_new_with_path(String id, String icon_name, int category, String icon_theme_path);
public int app_indicator_get_category(AppIndicatorInstanceStruct self);
public int app_indicator_get_status(AppIndicatorInstanceStruct self);
public String app_indicator_get_icon(AppIndicatorInstanceStruct self); void app_indicator_set_status(AppIndicatorInstanceStruct self, int status);
public String app_indicator_get_icon_desc(AppIndicatorInstanceStruct self);
public String app_indicator_get_icon_theme_path(AppIndicatorInstanceStruct self);
public String app_indicator_get_attention_icon(AppIndicatorInstanceStruct self);
public Pointer app_indicator_get_menu(AppIndicatorInstanceStruct self); void app_indicator_set_attention_icon(AppIndicatorInstanceStruct self, String icon_name);
public String app_indicator_get_label(AppIndicatorInstanceStruct self);
public String app_indicator_get_label_guide(AppIndicatorInstanceStruct self);
public int app_indicator_get_ordering_index(AppIndicatorInstanceStruct self);
public Pointer app_indicator_get_secondary_active_target(AppIndicatorInstanceStruct self);
public void app_indicator_build_menu_from_desktop(AppIndicatorInstanceStruct self, String desktop_file, String destkop_profile); void app_indicator_set_attention_icon_full(AppIndicatorInstanceStruct self, String name, String icon_desc);
}
void app_indicator_set_menu(AppIndicatorInstanceStruct self, Pointer menu);
void app_indicator_set_icon(AppIndicatorInstanceStruct self, String icon_name);
void app_indicator_set_icon_full(AppIndicatorInstanceStruct self, String icon_name, String icon_desc);
void app_indicator_set_label(AppIndicatorInstanceStruct self, String label, String guide);
void app_indicator_set_icon_theme_path(AppIndicatorInstanceStruct self, String icon_theme_path);
void app_indicator_set_ordering_index(AppIndicatorInstanceStruct self, int ordering_index);
void app_indicator_set_secondary_active_target(AppIndicatorInstanceStruct self, Pointer menuitem);
String app_indicator_get_id(AppIndicatorInstanceStruct self);
int app_indicator_get_category(AppIndicatorInstanceStruct self);
int app_indicator_get_status(AppIndicatorInstanceStruct self);
String app_indicator_get_icon(AppIndicatorInstanceStruct self);
String app_indicator_get_icon_desc(AppIndicatorInstanceStruct self);
String app_indicator_get_icon_theme_path(AppIndicatorInstanceStruct self);
String app_indicator_get_attention_icon(AppIndicatorInstanceStruct self);
Pointer app_indicator_get_menu(AppIndicatorInstanceStruct self);
String app_indicator_get_label(AppIndicatorInstanceStruct self);
String app_indicator_get_label_guide(AppIndicatorInstanceStruct self);
int app_indicator_get_ordering_index(AppIndicatorInstanceStruct self);
Pointer app_indicator_get_secondary_active_target(AppIndicatorInstanceStruct self);
void app_indicator_build_menu_from_desktop(AppIndicatorInstanceStruct self, String desktop_file, String destkop_profile);
}

View File

@ -5,8 +5,9 @@ import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
public interface GThread extends Library { public
public static final GThread INSTANCE = (GThread) Native.loadLibrary("gthread-2.0", GThread.class); interface GThread extends Library {
GThread INSTANCE = (GThread) Native.loadLibrary("gthread-2.0", GThread.class);
public void g_thread_init(Pointer GThreadFunctions); void g_thread_init(Pointer GThreadFunctions);
} }

View File

@ -1,69 +1,89 @@
package dorkbox.util.jna.linux; package dorkbox.util.jna.linux;
import com.sun.jna.*;
import dorkbox.util.Keep;
import dorkbox.util.jna.linux.Gtk.GdkEventButton;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import com.sun.jna.Callback; public
import com.sun.jna.Library; interface Gobject extends Library {
import com.sun.jna.Native; Gobject INSTANCE = (Gobject) Native.loadLibrary("gobject-2.0", Gobject.class);
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import dorkbox.util.Keep;
import dorkbox.util.jna.linux.Gtk.GdkEventButton;
public interface Gobject extends Library {
public static final Gobject INSTANCE = (Gobject) Native.loadLibrary("gobject-2.0", Gobject.class);
@Keep @Keep
public class GTypeClassStruct extends Structure { class GTypeClassStruct extends Structure {
public class ByValue extends GTypeClassStruct implements Structure.ByValue {} public
public class ByReference extends GTypeClassStruct implements Structure.ByReference {} class ByValue extends GTypeClassStruct implements Structure.ByValue {}
public
class ByReference extends GTypeClassStruct implements Structure.ByReference {}
public NativeLong g_type; public NativeLong g_type;
@Override @Override
protected List<String> getFieldOrder() { protected
List<String> getFieldOrder() {
return Arrays.asList("g_type"); return Arrays.asList("g_type");
} }
} }
@Keep @Keep
public class GTypeInstanceStruct extends Structure { class GTypeInstanceStruct extends Structure {
public class ByValue extends GTypeInstanceStruct implements Structure.ByValue {} public
public class ByReference extends GTypeInstanceStruct implements Structure.ByReference {} class ByValue extends GTypeInstanceStruct implements Structure.ByValue {}
public
class ByReference extends GTypeInstanceStruct implements Structure.ByReference {}
public Pointer g_class; public Pointer g_class;
@Override @Override
protected List<String> getFieldOrder() { protected
List<String> getFieldOrder() {
return Arrays.asList("g_class"); return Arrays.asList("g_class");
} }
} }
@Keep @Keep
public class GObjectStruct extends Structure { class GObjectStruct extends Structure {
public class ByValue extends GObjectStruct implements Structure.ByValue {} public
public class ByReference extends GObjectStruct implements Structure.ByReference {} class ByValue extends GObjectStruct implements Structure.ByValue {}
public
class ByReference extends GObjectStruct implements Structure.ByReference {}
public GTypeInstanceStruct g_type_instance; public GTypeInstanceStruct g_type_instance;
public int ref_count; public int ref_count;
public Pointer qdata; public Pointer qdata;
@Override @Override
protected List<String> getFieldOrder() { protected
return Arrays.asList("g_type_instance", List<String> getFieldOrder() {
"ref_count", return Arrays.asList("g_type_instance", "ref_count", "qdata");
"qdata");
} }
} }
@Keep @Keep
public class GObjectClassStruct extends Structure { class GObjectClassStruct extends Structure {
public class ByValue extends GObjectClassStruct implements Structure.ByValue {} public
public class ByReference extends GObjectClassStruct implements Structure.ByReference {} class ByValue extends GObjectClassStruct implements Structure.ByValue {}
public
class ByReference extends GObjectClassStruct implements Structure.ByReference {}
public GTypeClassStruct g_type_class; public GTypeClassStruct g_type_class;
public Pointer construct_properties; public Pointer construct_properties;
@ -84,55 +104,47 @@ public interface Gobject extends Library {
public Pointer dummy6; public Pointer dummy6;
@Override @Override
protected List<String> getFieldOrder() { protected
return Arrays.asList("g_type_class", List<String> getFieldOrder() {
"construct_properties", return Arrays.asList("g_type_class", "construct_properties", "constructor", "set_property", "get_property", "dispose",
"constructor", "finalize", "dispatch_properties_changed", "notify", "constructed", "flags", "dummy1", "dummy2", "dummy3",
"set_property", "dummy4", "dummy5", "dummy6");
"get_property",
"dispose",
"finalize",
"dispatch_properties_changed",
"notify",
"constructed",
"flags",
"dummy1",
"dummy2",
"dummy3",
"dummy4",
"dummy5",
"dummy6");
} }
} }
@Keep
public interface GCallback extends Callback {
public void callback(Pointer instance, Pointer data);
}
@Keep @Keep
public interface GEventCallback extends Callback { interface GCallback extends Callback {
public void callback(Pointer instance, GdkEventButton event); void callback(Pointer instance, Pointer data);
} }
@Keep @Keep
public class xyPointer extends Structure { interface GEventCallback extends Callback {
void callback(Pointer instance, GdkEventButton event);
}
@Keep
class xyPointer extends Structure {
public int value; public int value;
@Override @Override
protected List<String> getFieldOrder() { protected
List<String> getFieldOrder() {
return Arrays.asList("value"); return Arrays.asList("value");
} }
} }
@Keep @Keep
public interface GPositionCallback extends Callback { interface GPositionCallback extends Callback {
public void callback(Pointer menu, xyPointer x, xyPointer y, Pointer push_in_bool, Pointer user_data); void callback(Pointer menu, xyPointer x, xyPointer y, Pointer push_in_bool, Pointer user_data);
} }
public void g_object_unref(Pointer object); void g_object_unref(Pointer object);
public void g_signal_connect_data(Pointer instance, String detailed_signal, Callback c_handler,
Pointer data, Pointer destroy_data, int connect_flags); void g_signal_connect_data(Pointer instance, String detailed_signal, Callback c_handler, Pointer data, Pointer destroy_data,
int connect_flags);
} }

View File

@ -1,21 +1,21 @@
package dorkbox.util.jna.linux; package dorkbox.util.jna.linux;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; 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 java.util.Arrays;
import java.util.List;
public interface Gtk extends Library { public interface Gtk extends Library {
public static final Gtk INSTANCE = (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class); Gtk INSTANCE = (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class);
public static final int FALSE = 0; int FALSE = 0;
public static final int TRUE = 1; int TRUE = 1;
public static class GdkEventButton extends Structure { class GdkEventButton extends Structure {
public int type; public int type;
public Pointer window; public Pointer window;
public int send_event; public int send_event;
@ -46,39 +46,39 @@ public interface Gtk extends Library {
} }
} }
public 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 innermost invocation of the main loop return. * You can nest calls to gtk_main(). In that case gtk_main_quit() will make the innermost invocation of the main loop return.
*/ */
public 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 what you're doing! * you know what you're doing!
*/ */
public void gtk_main_quit(); void gtk_main_quit();
public void gdk_threads_init(); void gdk_threads_init();
public void gdk_threads_enter(); void gdk_threads_enter();
public void gdk_threads_leave(); void gdk_threads_leave();
public Pointer gtk_menu_new(); Pointer gtk_menu_new();
public Pointer gtk_menu_item_new_with_label(String label); Pointer gtk_menu_item_new_with_label(String label);
public Pointer gtk_status_icon_new(); Pointer gtk_status_icon_new();
public void gtk_status_icon_set_from_file(Pointer widget, String lablel); void gtk_status_icon_set_from_file(Pointer widget, String lablel);
public void gtk_status_icon_set_visible(Pointer widget, boolean visible); void gtk_status_icon_set_visible(Pointer widget, boolean visible);
public void gtk_status_icon_set_tooltip(Pointer widget, String tooltipText); void gtk_status_icon_set_tooltip(Pointer widget, String tooltipText);
public void gtk_menu_item_set_label(Pointer menu_item, String label); void gtk_menu_item_set_label(Pointer menu_item, String label);
public void gtk_menu_shell_append(Pointer menu_shell, Pointer child); void gtk_menu_shell_append(Pointer menu_shell, Pointer child);
public void gtk_widget_set_sensitive(Pointer widget, int sesitive); void gtk_widget_set_sensitive(Pointer widget, int sesitive);
public void gtk_widget_show(Pointer widget); void gtk_widget_show(Pointer widget);
public void gtk_widget_show_all(Pointer widget); void gtk_widget_show_all(Pointer widget);
public void gtk_widget_destroy(Pointer widget); void gtk_widget_destroy(Pointer widget);
} }

View File

@ -3,65 +3,74 @@ package dorkbox.util.jna.linux;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
public class GtkSupport { public
class GtkSupport {
public static final boolean isSupported; public static final boolean isSupported;
private static boolean hasSwt = false; private static boolean hasSwt = false;
static { static {
if (Gtk.INSTANCE != null && AppIndicator.INSTANCE != null && Gobject.INSTANCE != null && GThread.INSTANCE != null) { boolean hasSupport = false;
isSupported = true; try {
if (Gtk.INSTANCE != null && Gobject.INSTANCE != null && GThread.INSTANCE != null) {
try { hasSupport = true;
Class<?> swtClass = Class.forName("org.eclipse.swt.widgets.Display");
if (swtClass != null) {
hasSwt = true;
}
} catch (Exception ignore) {}
// If we are using GTK, we need to make sure the event loop is running. There can be multiple/nested loops.
// since SWT uses one already, it's not necessary to have two.
if (!hasSwt) {
Gtk instance = Gtk.INSTANCE;
instance.gtk_init(0, null);
GThread.INSTANCE.g_thread_init(null);
instance.gdk_threads_init();
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
Thread gtkUpdateThread = new Thread() {
@Override
public void run() {
Gtk instance = Gtk.INSTANCE;
// notify our main thread to continue
blockUntilStarted.countDown();
instance.gdk_threads_enter();
instance.gtk_main();
// MUST leave as well!
instance.gdk_threads_leave();
}
};
gtkUpdateThread.setName("GTK Event Loop");
gtkUpdateThread.start();
try { try {
// we CANNOT continue until the GTK thread has started! (ignored if SWT is used) Class<?> swtClass = Class.forName("org.eclipse.swt.widgets.Display");
blockUntilStarted.await(); if (swtClass != null) {
} catch (InterruptedException e) { hasSwt = true;
e.printStackTrace(); }
} catch (Throwable ignore) {
}
// If we are using GTK, we need to make sure the event loop is running. There can be multiple/nested loops.
// since SWT uses one already, it's not necessary to have two.
if (!hasSwt) {
Gtk instance = Gtk.INSTANCE;
instance.gtk_init(0, null);
GThread.INSTANCE.g_thread_init(null);
instance.gdk_threads_init();
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
Thread gtkUpdateThread = new Thread() {
@Override
public
void run() {
Gtk instance = Gtk.INSTANCE;
// notify our main thread to continue
blockUntilStarted.countDown();
instance.gdk_threads_enter();
instance.gtk_main();
// MUST leave as well!
instance.gdk_threads_leave();
}
};
gtkUpdateThread.setName("GTK Event Loop");
gtkUpdateThread.start();
try {
// we CANNOT continue until the GTK thread has started! (ignored if SWT is used)
blockUntilStarted.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} }
} else { } catch (Throwable ignored) {
isSupported = false;
} }
isSupported = hasSupport;
} }
public static void init() { public static
void init() {
// placeholder to init GTK // placeholder to init GTK
} }
public static void shutdownGTK() { public static
if (!hasSwt) { void shutdownGTK() {
if (isSupported && !hasSwt) {
Gtk.INSTANCE.gtk_main_quit(); Gtk.INSTANCE.gtk_main_quit();
} }
} }