/* * 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 #include #include #include #ifndef __USE_GNU // required for dladdr() & Dl_info #define __USE_GNU #endif #include #include #include #include #include #include #include #include #include #define LOAD_SYMBOL(s, x) \ if (s == NULL) { \ s = dlsym(libraryHandle, #x); \ if (s == NULL) { \ fprintf(stderr,"failed loading %s\n", #x); \ exit(-1); \ } else { \ fprintf(stderr,"loading %s\n", #x); \ } \ } else { \ fprintf(stderr,"have %s\n", #x); \ } static const char * gtk2_chain[] = { "libglassgtk2.so", "libglassgtk3.so", 0 }; static const char * gtk3_chain[] = { "libglassgtk3.so", "libglassgtk2.so", 0 }; static JavaVM* javaVM; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { (void) reserved; javaVM = jvm; // better way to get/save this? return JNI_VERSION_1_6; } // our library combinations defined // "version" "libgtk", "libdgdk", "libpixbuf" // note that currently only the first char of the version is used static char * gtk2_versioned[] = { "2", "libgtk-x11-2.0.so.0", "libgdk-x11-2.0.so.0", "libgdk_pixbuf-2.0.so" }; static char * gtk2_not_versioned[] = { "2", "libgtk-x11-2.0.so", "libgdk-x11-2.0.so", "libgdk_pixbuf-2.0.so" }; static char * gtk3_versioned[] = { "3", "libgtk-3.so.0", "libgdk-3.so.0", "libgdk_pixbuf-2.0.so.0" }; static char * gtk3_not_versioned[] = { "3", "libgtk-3.so", "libgdk-3.so", "libgdk_pixbuf-2.0.so" }; // our library set orders defined, null terminated static char ** two_to_three[] = { gtk2_versioned, gtk2_not_versioned, gtk3_versioned, gtk3_not_versioned, 0 }; static char ** three_to_two[] = { gtk3_versioned, gtk3_not_versioned, gtk2_versioned, gtk2_not_versioned, 0 }; static int try_opening_libraries(char *names[3]) { void * gtk; void * gdk; void * pix; gtk = dlopen (names[1], RTLD_LAZY | RTLD_GLOBAL); if (!gtk) { return 0; } gdk = dlopen (names[2], RTLD_LAZY | RTLD_GLOBAL); if (!gdk) { dlclose(gtk); return 0; } pix = dlopen (names[3], RTLD_LAZY | RTLD_GLOBAL); if (!pix) { dlclose(gtk); dlclose(gdk); gtk = gdk = 0; return 0; } dlclose(gtk); dlclose(gdk); dlclose(pix); return 1; } static int sniffLibs(int wantVersion) { printf("trying for version %d\n",wantVersion); int success = 1; char *** use_chain; int wrapper_gtk_version; int wrapper_gtk_versionDebug = 1; if (wantVersion == 0 || wantVersion == 2) { use_chain = two_to_three; wrapper_gtk_version = 2; } else if (wantVersion == 3) { use_chain = three_to_two; wrapper_gtk_version = 3; } else { printf(" Huh ? what version is %d\n", wantVersion); exit (-3); } int i, found = 0; for(i = 0; use_chain[i] && !found; i++) { if (wrapper_gtk_versionDebug) { printf("trying GTK library set %s, %s, %s\n", use_chain[i][1], use_chain[i][2], use_chain[i][3]); } found = try_opening_libraries(use_chain[i]); if (found) { if (use_chain[i][0][0] == '2') { wrapper_gtk_version = 2; } else { wrapper_gtk_version = 3; } } } if (found) { if (wrapper_gtk_versionDebug) { i--; printf("using GTK library version %s set %s, %s, %s\n", use_chain[i][0], use_chain[i][1], use_chain[i][2], use_chain[i][3]); } return use_chain[i][0][0]; } return -1; } /* * Class: com_sun_glass_ui_gtk_GtkApplication * Method: _queryLibrary * Signature: Signature: (IZ)I */ JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1queryLibrary (JNIEnv *env, jclass clazz, jint suggestedVersion, jboolean verbose) { (void) env; (void) clazz; (void) verbose; // Before doing anything with GTK we validate that the DISPLAY can be opened Display *display = XOpenDisplay(NULL); if (display == NULL) { return com_sun_glass_ui_gtk_GtkApplication_QUERY_NO_DISPLAY; } XCloseDisplay(display); // now check the the presence of the libraries char version = sniffLibs(suggestedVersion); if (version == '2') { return com_sun_glass_ui_gtk_GtkApplication_QUERY_LOAD_GTK2; } else if (version == '3') { return com_sun_glass_ui_gtk_GtkApplication_QUERY_LOAD_GTK3; } return com_sun_glass_ui_gtk_GtkApplication_QUERY_ERROR; }