
dorkbox.util.jna.linux.AppIndicator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of SystemTray Show documentation
Show all versions of SystemTray Show documentation
Cross-platform SystemTray support for Swing/AWT, GtkStatusIcon, and AppIndicator on Java 6+
/*
* 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 org.slf4j.LoggerFactory;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import dorkbox.util.OS;
import dorkbox.util.jna.JnaHelper;
import dorkbox.util.jna.linux.structs.AppIndicatorInstanceStruct;
/**
* bindings for libappindicator
*
* Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md
*/
@SuppressWarnings({"Duplicates", "SameParameterValue", "DanglingJavadoc"})
public
class AppIndicator {
public static final boolean isVersion3;
public static final boolean isLoaded;
/**
* Loader 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/API set is. We just try until we find one that works, and are able to map the
* symbols we need. There are bash commands that will tell us the linked library name, however - I'd rather not run bash commands
* to determine this.
*
* This is so hacky it makes me sick.
*/
static {
boolean _isVersion3 = false;
boolean _isLoaded = false;
boolean shouldLoadAppIndicator = !(OS.isWindows() || OS.isMacOsX());
if (!shouldLoadAppIndicator) {
_isLoaded = true;
}
// objdump -T /usr/lib/x86_64-linux-gnu/libappindicator.so.1 | grep foo
// objdump -T /usr/lib/x86_64-linux-gnu/libappindicator3.so.1 | grep foo
// NOTE:
// ALSO WHAT VERSION OF GTK to use? appindiactor1 -> GTK2, appindicator3 -> GTK3.
// appindiactor1 is GKT2 only (can't use GTK3 bindings with it)
// appindicator3 doesn't support menu icons via GTK2!!
// if (!_isLoaded && SystemTray.FORCE_TRAY_TYPE == SystemTray.TrayType.GtkStatusIcon) {
// // if we force GTK type system tray, don't attempt to load AppIndicator libs
// if (GtkEventDispatch.DEBUG) {
// LoggerFactory.getLogger(AppIndicator.class).debug("Forced GtkStatusIcon tray type, not using AppIndicator");
// }
// _isLoaded = true;
// }
if (!_isLoaded && GtkEventDispatch.FORCE_GTK2) {
// if specified, try loading appindicator1 first, maybe it's there?
// note: we can have GTK2 + appindicator3, but NOT ALWAYS.
try {
// deliberately without the "1" at the end.
final NativeLibrary library = JnaHelper.register("appindicator", AppIndicator.class);
if (library != null) {
_isLoaded = true;
}
} catch (Throwable e) {
if (GtkEventDispatch.DEBUG) {
LoggerFactory.getLogger(AppIndicator.class).debug("Error loading GTK2 explicit appindicator. {}", e.getMessage());
}
}
}
String nameToCheck1;
String nameToCheck2;
if (Gtk.isGtk2) {
nameToCheck1 = "appindicator"; // deliberately without the "1" at the end.
}
else {
nameToCheck1 = "appindicator3";
}
// start with base version using whatever the OS specifies as the proper symbolic link
if (!_isLoaded) {
try {
final NativeLibrary library = JnaHelper.register(nameToCheck1, AppIndicator.class);
String s = library.getFile().getName();
if (GtkEventDispatch.DEBUG) {
LoggerFactory.getLogger(AppIndicator.class).debug("Loading library (first attempt): '{}'", s);
}
if (s.contains("appindicator3")) {
_isVersion3 = true;
}
_isLoaded = true;
} catch (Throwable e) {
if (GtkEventDispatch.DEBUG) {
LoggerFactory.getLogger(AppIndicator.class).debug("Error loading library: '{}'. \n{}", nameToCheck1, e.getMessage());
}
}
}
// maybe it's really GTK2 version? who knows...
if (!_isLoaded) {
try {
JnaHelper.register("appindicator", AppIndicator.class);
_isLoaded = true;
} catch (Throwable e) {
if (GtkEventDispatch.DEBUG) {
LoggerFactory.getLogger(AppIndicator.class).debug("Error loading library: '{}'. \n{}", "appindicator", e.getMessage());
}
}
}
// If we are GTK2, change the order we check and load libraries
if (Gtk.isGtk2) {
nameToCheck1 = "appindicator-gtk";
nameToCheck2 = "appindicator-gtk3";
}
else {
nameToCheck1 = "appindicator-gtk3";
nameToCheck2 = "appindicator-gtk";
}
// another type. who knows...
if (!_isLoaded) {
try {
JnaHelper.register(nameToCheck1, AppIndicator.class);
_isLoaded = true;
} catch (Throwable e) {
if (GtkEventDispatch.DEBUG) {
LoggerFactory.getLogger(AppIndicator.class).debug("Error loading library: '{}'. \n{}", nameToCheck1, e.getMessage());
}
}
}
// this is HORRID. such a PITA
if (!_isLoaded) {
try {
JnaHelper.register(nameToCheck2, AppIndicator.class);
_isLoaded = true;
} catch (Throwable e) {
if (GtkEventDispatch.DEBUG) {
LoggerFactory.getLogger(AppIndicator.class).debug("Error loading library: '{}'. \n{}", nameToCheck2, e.getMessage());
}
}
}
// We fall back to GtkStatusIndicator or Swing if this cannot load
if (shouldLoadAppIndicator && _isLoaded) {
isLoaded = true;
isVersion3 = _isVersion3;
} else {
isLoaded = false;
isVersion3 = false;
}
}
// Note: AppIndicators DO NOT support tooltips, as per mark shuttleworth. Rather stupid IMHO.
// See: https://bugs.launchpad.net/indicator-application/+bug/527458/comments/12
public static final int CATEGORY_APPLICATION_STATUS = 0;
// public static final int CATEGORY_COMMUNICATIONS = 1;
// public static final int CATEGORY_SYSTEM_SERVICES = 2;
// public static final int CATEGORY_HARDWARE = 3;
// public static final int CATEGORY_OTHER = 4;
public static final int STATUS_PASSIVE = 0;
public static final int STATUS_ACTIVE = 1;
// public static final int STATUS_ATTENTION = 2;
public static native
AppIndicatorInstanceStruct app_indicator_new(String id, String icon_name, int category);
public static native void app_indicator_set_title(Pointer indicator, String title);
public static native void app_indicator_set_status(Pointer indicator, int status);
public static native void app_indicator_set_menu(Pointer indicator, Pointer menu);
public static native void app_indicator_set_icon(Pointer indicator, String icon_name);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy