diff --git a/Dorkbox-Util/src/dorkbox/util/jna/linux/AppIndicator.java b/Dorkbox-Util/src/dorkbox/util/jna/linux/AppIndicator.java index 47377a2..f33c272 100644 --- a/Dorkbox-Util/src/dorkbox/util/jna/linux/AppIndicator.java +++ b/Dorkbox-Util/src/dorkbox/util/jna/linux/AppIndicator.java @@ -15,18 +15,22 @@ */ package dorkbox.util.jna.linux; -import com.sun.jna.*; +import com.sun.jna.Library; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; import dorkbox.util.Keep; -import dorkbox.util.jna.linux.Gobject.GObjectClassStruct; import dorkbox.util.jna.linux.Gobject.GObjectStruct; import java.util.Arrays; import java.util.List; -/* bindings for libappindicator 0.1 */ +/* bindings for libappindicator */ public interface AppIndicator extends Library { - AppIndicator INSTANCE = (AppIndicator) Native.loadLibrary("appindicator", AppIndicator.class); + // effing retarded. There are DIFFERENT versions, of which they all share the same basic compatibility (of the methods that + // we use), however -- we cannot just LOAD via the 'base-name', we actually have to try each one. There are bash commands that + // will tell us the linked library name, however - I'd rather not run bash commands to determine this. + AppIndicator INSTANCE = (AppIndicator) AppIndicatorQuery.get(); int CATEGORY_APPLICATION_STATUS = 0; int CATEGORY_COMMUNICATIONS = 1; @@ -39,65 +43,6 @@ interface AppIndicator extends Library { int STATUS_ATTENTION = 2; - @Keep - interface Fallback extends Callback { - Pointer callback(AppIndicatorInstanceStruct self); - } - - - @Keep - interface Unfallback extends Callback { - 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 Pointer new_icon; - public Pointer new_attention_icon; - public Pointer new_status; - public Pointer new_icon_theme; - public Pointer new_label; - public Pointer connection_changed; - public Pointer scroll_event; - public Pointer app_indicator_reserved_ats; - public Fallback fallback; - public Pointer unfallback; - public Pointer app_indicator_reserved_1; - public Pointer app_indicator_reserved_2; - public Pointer app_indicator_reserved_3; - public Pointer app_indicator_reserved_4; - public Pointer app_indicator_reserved_5; - public Pointer app_indicator_reserved_6; - - public - AppIndicatorClassStruct() { - } - - public - AppIndicatorClassStruct(Pointer p) { - super(p); - useMemory(p); - read(); - } - - @Override - protected - List getFieldOrder() { - return Arrays.asList("parent_class", "new_icon", "new_attention_icon", "new_status", "new_icon_theme", "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 class AppIndicatorInstanceStruct extends Structure { public GObjectStruct parent; @@ -110,54 +55,12 @@ interface AppIndicator extends Library { } } + // Note: AppIndicators DO NOT support tooltips, as per mark shuttleworth. Rather stupid IMHO. + // See: https://bugs.launchpad.net/indicator-application/+bug/527458/comments/12 AppIndicatorInstanceStruct app_indicator_new(String id, String icon_name, int category); - AppIndicatorInstanceStruct app_indicator_new_with_path(String id, String icon_name, int category, String icon_theme_path); - void app_indicator_set_status(AppIndicatorInstanceStruct self, int status); - - void app_indicator_set_attention_icon(AppIndicatorInstanceStruct self, String icon_name); - - 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); } diff --git a/Dorkbox-Util/src/dorkbox/util/jna/linux/AppIndicatorQuery.java b/Dorkbox-Util/src/dorkbox/util/jna/linux/AppIndicatorQuery.java new file mode 100644 index 0000000..1b3d344 --- /dev/null +++ b/Dorkbox-Util/src/dorkbox/util/jna/linux/AppIndicatorQuery.java @@ -0,0 +1,86 @@ +/* + * Copyright 2015 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dorkbox.util.jna.linux; + +import com.sun.jna.Native; + +/** + * Helper for AppIndicator, because it is absolutely mindboggling how those whom maintain the standard, can't agree to what that standard + * library naming convention or features rae is. We just try until we find one that work, and are able to map the symbols we need. + */ +public +class AppIndicatorQuery { + public static + Object get() { + Object library; + + // start with base version + try { + library = Native.loadLibrary("appindicator", AppIndicator.class); + if (library != null) { + return library; + } + } catch (Throwable ignored) { + } + + // version 1 is better than version 3, because of dumb shit redhat did. + try { + library = Native.loadLibrary("appindicator1", AppIndicator.class); + if (library != null) { + return library; + } + } catch (Throwable ignored) { + } + + // now check all others. super hacky way to do this. + for (int i = 10; i >= 0; i--) { + try { + library = Native.loadLibrary("appindicator" + i, AppIndicator.class); + if (library != null) { + if (i == 3) { + System.err.println("AppIndicator3 detected. This version is SEVERELY limited, and menu icons WILL NOT be visible. " + + "Please install a better version of libappindicator. One such command to do so is: " + + "sudo apt-get install libappindicator1"); + } + return library; + } + } catch (Throwable ignored) { + } + } + + // another type. who knows... + try { + library = Native.loadLibrary("appindicator-gtk", AppIndicator.class); + if (library != null) { + return library; + } + } catch (Throwable ignored) { + } + + // this is HORRID. such a PITA + try { + library = Native.loadLibrary("appindicator-gtk3", AppIndicator.class); + if (library != null) { + return library; + } + } catch (Throwable ignored) { + } + + throw new RuntimeException("We apologize for this, but we are unable to determine the appIndicator 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."); + } +} diff --git a/Dorkbox-Util/src/dorkbox/util/jna/linux/Gobject.java b/Dorkbox-Util/src/dorkbox/util/jna/linux/Gobject.java index a46c142..62d2b7c 100644 --- a/Dorkbox-Util/src/dorkbox/util/jna/linux/Gobject.java +++ b/Dorkbox-Util/src/dorkbox/util/jna/linux/Gobject.java @@ -129,7 +129,10 @@ interface Gobject extends Library { @Keep interface GCallback extends Callback { - void callback(Pointer instance, Pointer data); + /** + * @return Gtk.TRUE if we handled this event + */ + int callback(Pointer instance, Pointer data); } @@ -158,11 +161,15 @@ interface Gobject extends Library { - + void g_free(Pointer object); void g_object_unref(Pointer object); NativeLong g_signal_connect_data(Pointer instance, String detailed_signal, Callback c_handler, Pointer data, Pointer destroy_data, int connect_flags); NativeLong g_signal_connect(Pointer instance, String detailed_signal, Callback c_handler, Pointer data); + + void g_signal_handler_disconnect(Pointer instance, NativeLong longAddress); + + Pointer g_markup_printf_escaped(String pattern, String inputString); } diff --git a/Dorkbox-Util/src/dorkbox/util/jna/linux/Gtk.java b/Dorkbox-Util/src/dorkbox/util/jna/linux/Gtk.java index 8efab6f..491802f 100644 --- a/Dorkbox-Util/src/dorkbox/util/jna/linux/Gtk.java +++ b/Dorkbox-Util/src/dorkbox/util/jna/linux/Gtk.java @@ -26,11 +26,15 @@ 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); 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 { public int type; @@ -83,20 +87,40 @@ public interface Gtk extends Library { 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. + Pointer gtk_image_new_from_file(String iconPath); + + + 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); - void gtk_status_icon_set_tooltip(Pointer widget, String tooltipText); + + // app indicators don't support this, and we cater to the lowest common denominator +// void gtk_status_icon_set_tooltip(Pointer widget, String tooltipText); void gtk_status_icon_set_title(Pointer widget, String titleText); 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_widget_set_sensitive(Pointer widget, int sesitive); + void gtk_menu_shell_prepend(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_show(Pointer widget); void gtk_widget_show_all(Pointer widget);