/* * Copyright (c) 2015, 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 #include "jvm_md.h" #include #include #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"); } 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, fp_dbusmenu_menuitem_property_get_int(mi, "toggle-state") ? JNI_FALSE : JNI_TRUE); } /* * 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) { 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 (gtk2_load(env) && 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) { fp_gdk_threads_enter(); fp_gtk_main(); fp_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) { fp_gdk_threads_enter(); fp_unity_launcher_entry_set_count(entry, value); fp_unity_launcher_entry_set_count_visible(entry, visible); fp_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) { fp_gdk_threads_enter(); fp_unity_launcher_entry_set_urgent(entry, urgent); fp_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) { fp_gdk_threads_enter(); fp_unity_launcher_entry_set_progress(entry, value); fp_unity_launcher_entry_set_progress_visible(entry, visible); fp_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 = fp_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); fp_dbusmenu_menuitem_child_append(menu, mi); fp_g_signal_connect(mi, "item_activated", G_CALLBACK(callback), elem); } } } } /* * Class: sun_awt_X11_XTaskbarPeer * Method: setNativeMenu * Signature: ([Ljava/awt/MenuItem;)V */ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setNativeMenu (JNIEnv *env, jobject obj, jobjectArray items) { fp_gdk_threads_enter(); if (!menu) { menu = fp_dbusmenu_menuitem_new(); fp_unity_launcher_entry_set_quicklist(entry, menu); } GList* list = fp_dbusmenu_menuitem_take_children(menu); fp_g_list_free_full(list, fp_g_object_unref); fp_g_list_free_full(globalRefs, deleteGlobalRef); globalRefs = NULL; if (items) { fill_menu(env, items); } fp_gdk_threads_leave(); }