/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <dlfcn.h>
#include "jvm_md.h"
#include <setjmp.h>
#include <string.h>
#include "jni_util.h"
#include "awt_Taskbar.h"
extern JavaVM *jvm;
#define NO_SYMBOL_EXCEPTION 1
#define UNITY_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("unity", "9")
#define UNITY_LIB JNI_LIB_NAME("unity")
static jmp_buf j;
static void *unity_libhandle = NULL;
static DbusmenuMenuitem* menu = NULL;
UnityLauncherEntry* entry = NULL;
static jclass jTaskbarCls = NULL;
static jmethodID jTaskbarCallback = NULL;
static jmethodID jMenuItemGetLabel = NULL;
GList* globalRefs = NULL;
static void* dl_symbol(const char* name) {
void* result = dlsym(unity_libhandle, name);
if (!result)
longjmp(j, NO_SYMBOL_EXCEPTION);
return result;
}
static gboolean unity_load() {
unity_libhandle = dlopen(UNITY_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
if (unity_libhandle == NULL) {
unity_libhandle = dlopen(UNITY_LIB, RTLD_LAZY | RTLD_LOCAL);
if (unity_libhandle == NULL) {
return FALSE;
}
}
if (setjmp(j) == 0) {
fp_unity_launcher_entry_get_for_desktop_file = dl_symbol("unity_launcher_entry_get_for_desktop_file");
fp_unity_launcher_entry_set_count = dl_symbol("unity_launcher_entry_set_count");
fp_unity_launcher_entry_set_count_visible = dl_symbol("unity_launcher_entry_set_count_visible");
fp_unity_launcher_entry_set_urgent = dl_symbol("unity_launcher_entry_set_urgent");
fp_unity_launcher_entry_set_progress = dl_symbol("unity_launcher_entry_set_progress");
fp_unity_launcher_entry_set_progress_visible = dl_symbol("unity_launcher_entry_set_progress_visible");
fp_dbusmenu_menuitem_new = dl_symbol("dbusmenu_menuitem_new");
fp_dbusmenu_menuitem_property_set = dl_symbol("dbusmenu_menuitem_property_set");
fp_dbusmenu_menuitem_property_set_int = dl_symbol("dbusmenu_menuitem_property_set_int");
fp_dbusmenu_menuitem_property_get_int = dl_symbol("dbusmenu_menuitem_property_get_int");
fp_dbusmenu_menuitem_property_set = dl_symbol("dbusmenu_menuitem_property_set");
fp_dbusmenu_menuitem_child_append = dl_symbol("dbusmenu_menuitem_child_append");
fp_dbusmenu_menuitem_child_delete = dl_symbol("dbusmenu_menuitem_child_delete");
fp_dbusmenu_menuitem_take_children = dl_symbol("dbusmenu_menuitem_take_children");
fp_dbusmenu_menuitem_foreach = dl_symbol("dbusmenu_menuitem_foreach");
fp_unity_launcher_entry_set_quicklist = dl_symbol("unity_launcher_entry_set_quicklist");
fp_unity_launcher_entry_get_quicklist = dl_symbol("unity_launcher_entry_get_quicklist");
} else {
dlclose(unity_libhandle);
unity_libhandle = NULL;
return FALSE;
}
return TRUE;
}
void callback(DbusmenuMenuitem* mi, guint ts, jobject data) {
JNIEnv* env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2);
(*env)->CallStaticVoidMethod(env, jTaskbarCls, jTaskbarCallback, data);
}
/*
* Class: sun_awt_X11_XTaskbarPeer
* Method: init
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XTaskbarPeer_init
(JNIEnv *env, jclass cls, jstring jname, jint version, jboolean verbose) {
jclass clazz;
jTaskbarCls = (*env)->NewGlobalRef(env, cls);
CHECK_NULL_RETURN(jTaskbarCallback =
(*env)->GetStaticMethodID(env, cls, "menuItemCallback", "(Ljava/awt/MenuItem;)V"), JNI_FALSE);
CHECK_NULL_RETURN(
clazz = (*env)->FindClass(env, "java/awt/MenuItem"), JNI_FALSE);
CHECK_NULL_RETURN(
jMenuItemGetLabel = (*env)->GetMethodID(env, clazz, "getLabel", "()Ljava/lang/String;"), JNI_FALSE);
if (gtk_load(env, version, verbose) && unity_load()) {
const gchar* name = (*env)->GetStringUTFChars(env, jname, NULL);
if (name) {
entry = fp_unity_launcher_entry_get_for_desktop_file(name);
(*env)->ReleaseStringUTFChars(env, jname, name);
return JNI_TRUE;
}
}
return JNI_FALSE;
}
/*
* Class: sun_awt_X11_XTaskbarPeer
* Method: runloop
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_runloop
(JNIEnv *env, jclass cls) {
gtk->gdk_threads_enter();
gtk->gtk_main();
gtk->gdk_threads_leave();
}
/*
* Class: sun_awt_X11_XTaskbarPeer
* Method: setBadge
* Signature: (JZ)V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setBadge
(JNIEnv *env, jobject obj, jlong value, jboolean visible) {
gtk->gdk_threads_enter();
fp_unity_launcher_entry_set_count(entry, value);
fp_unity_launcher_entry_set_count_visible(entry, visible);
DbusmenuMenuitem* m;
if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
fp_unity_launcher_entry_set_quicklist(entry, m);
}
gtk->gdk_threads_leave();
}
/*
* Class: sun_awt_X11_XTaskbarPeer
* Method: setUrgent
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setUrgent
(JNIEnv *env, jobject obj, jboolean urgent) {
gtk->gdk_threads_enter();
fp_unity_launcher_entry_set_urgent(entry, urgent);
DbusmenuMenuitem* m;
if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
fp_unity_launcher_entry_set_quicklist(entry, m);
}
gtk->gdk_threads_leave();
}
/*
* Class: sun_awt_X11_XTaskbarPeer
* Method: updateProgress
* Signature: (DZ)V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_updateProgress
(JNIEnv *env, jobject obj, jdouble value, jboolean visible) {
gtk->gdk_threads_enter();
fp_unity_launcher_entry_set_progress(entry, value);
fp_unity_launcher_entry_set_progress_visible(entry, visible);
DbusmenuMenuitem* m;
if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
fp_unity_launcher_entry_set_quicklist(entry, m);
}
gtk->gdk_threads_leave();
}
void deleteGlobalRef(gpointer data) {
JNIEnv* env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2);
(*env)->DeleteGlobalRef(env, data);
}
void fill_menu(JNIEnv *env, jobjectArray items) {
int index;
jsize length = (*env)->GetArrayLength(env, items);
for (index = 0; index < length; index++) {
jobject elem = (*env)->GetObjectArrayElement(env, items, index);
if ((*env)->ExceptionCheck(env)) {
break;
}
elem = (*env)->NewGlobalRef(env, elem);
globalRefs = gtk->g_list_append(globalRefs, elem);
jstring jlabel = (jstring) (*env)->CallObjectMethod(env, elem, jMenuItemGetLabel);
if (!(*env)->ExceptionCheck(env) && jlabel) {
const gchar* label = (*env)->GetStringUTFChars(env, jlabel, NULL);
if (label) {
DbusmenuMenuitem* mi = fp_dbusmenu_menuitem_new();
if (!strcmp(label, "-")) {
fp_dbusmenu_menuitem_property_set(mi, "type", "separator");
} else {
fp_dbusmenu_menuitem_property_set(mi, "label", label);
}
(*env)->ReleaseStringUTFChars(env, jlabel, label);
/**代码未完, 请加载全部代码(NowJava.com).**/