1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <linux/fb.h> 29 #include <fcntl.h> 30 #ifndef __USE_GNU // required for dladdr() & Dl_info 31 #define __USE_GNU 32 #endif 33 #include <dlfcn.h> 34 #include <sys/ioctl.h> 35 36 #include <string.h> 37 #include <strings.h> 38 #include <stdlib.h> 39 40 #include <assert.h> 41 42 #include <gtk/gtk.h> 43 44 #include "glass_wrapper.h" 45 46 int wrapper_debug = 0; // enable for development only 47 int wrapper_loaded = 0; 48 int wrapper_gtk_version = 0; 49 int wrapper_gtk_versionDebug = 0; 50 51 // our library combinations defined 52 // "version" "libgtk", "libdgdk", "libpixbuf" 53 // note that currently only the first char of the version is used 54 static char * gtk2_versioned[] = { 55 "2", "libgtk-x11-2.0.so.0", "libgdk-x11-2.0.so.0", "libgdk_pixbuf-2.0.so" 56 }; 57 58 static char * gtk2_not_versioned[] = { 59 "2", "libgtk-x11-2.0.so", "libgdk-x11-2.0.so", "libgdk_pixbuf-2.0.so" 60 }; 61 62 static char * gtk3_versioned[] = { 63 "3", "libgtk-3.so.0", "libgdk-3.so.0", "libgdk_pixbuf-2.0.so.0" 64 }; 65 66 static char * gtk3_not_versioned[] = { 67 "3", "libgtk-3.so", "libgdk-3.so", "libgdk_pixbuf-2.0.so" 68 }; 69 70 // our library set orders defined, null terminated 71 static char ** two_to_three[] = { 72 gtk2_versioned, gtk2_not_versioned, 73 gtk3_versioned, gtk3_not_versioned, 74 0 75 }; 76 77 static char ** three_to_two[] = { 78 gtk3_versioned, gtk3_not_versioned, 79 gtk2_versioned, gtk2_not_versioned, 80 0 81 }; 82 83 static int try_opening_libraries(char *names[3], void** gtk, void** gdk, void ** pix) 84 { 85 *gtk = dlopen (names[1], RTLD_LAZY | RTLD_GLOBAL); 86 if (!*gtk) { 87 if (wrapper_gtk_versionDebug) { 88 fprintf(stderr, "failed to load %s\n", names[1]); 89 } 90 return 0; 91 } 92 93 *gdk = dlopen (names[2], RTLD_LAZY | RTLD_GLOBAL); 94 if (!*gdk) { 95 if (wrapper_gtk_versionDebug) { 96 fprintf(stderr, "failed to load %s\n", names[2]); 97 } 98 dlclose(*gtk); 99 *gtk = 0; 100 return 0; 101 } 102 103 *pix = dlopen (names[3], RTLD_LAZY | RTLD_GLOBAL); 104 if (!*pix) { 105 if (wrapper_gtk_versionDebug) { 106 fprintf(stderr, "failed to load %s\n", names[3]); 107 } 108 dlclose(*gtk); 109 dlclose(*gdk); 110 *gtk = *gdk = 0; 111 return 0; 112 } 113 114 return 1; 115 } 116 117 int wrapper_load_symbols(int version, int verbose) { 118 if (wrapper_loaded) { 119 return wrapper_gtk_version; 120 } 121 122 wrapper_gtk_versionDebug = verbose; 123 124 void *libgtk = 0, *libgdk = 0, *libpix = 0; 125 126 int success = 1; 127 char *** use_chain; 128 129 if (version == 3) { 130 use_chain = three_to_two; 131 wrapper_gtk_version = 3; 132 } else if (version == 0 || version == 2) { 133 use_chain = two_to_three; 134 wrapper_gtk_version = 2; 135 } else { 136 // should never happen, java should pass validated values 137 fprintf(stderr, "Unrecognized GTK version requested, falling back to v 2.0\n"); 138 fflush(stderr); 139 use_chain = two_to_three; 140 wrapper_gtk_version = 2; 141 } 142 143 if (wrapper_gtk_versionDebug) { 144 fprintf(stderr, "Loading GTK libraries version %d\n", version); 145 } 146 147 int i, found = 0; 148 for(i = 0; use_chain[i] && !found; i++) { 149 if (wrapper_gtk_versionDebug) { 150 printf("trying GTK library set %s, %s, %s\n", 151 use_chain[i][1], 152 use_chain[i][2], 153 use_chain[i][3]); 154 } 155 found = try_opening_libraries(use_chain[i], &libgtk, &libgdk, &libpix); 156 157 if (found) { 158 if (use_chain[i][0][0] == '2') { 159 wrapper_gtk_version = 2; 160 } else { // (use_chain[i][1][0] == '3') { 161 wrapper_gtk_version = 3; 162 } 163 164 if (wrapper_load_symbols_gtk(wrapper_gtk_version, libgtk) != 0) { 165 found = 0; 166 } else if (wrapper_load_symbols_gdk(wrapper_gtk_version, libgdk) != 0) { 167 found = 0; 168 } else if (wrapper_load_symbols_pix(wrapper_gtk_version, libpix) != 0) { 169 found = 0; 170 } 171 } 172 173 if (!found) { 174 if (libgtk) dlclose(libgtk); 175 if (libgdk) dlclose(libgdk); 176 if (libpix) dlclose(libpix); 177 } 178 } 179 180 if (found) { 181 if (wrapper_gtk_versionDebug) { 182 i--; 183 printf("using GTK library set %s, %s, %s\n", 184 use_chain[i][1], 185 use_chain[i][2], 186 use_chain[i][3]); 187 } 188 } else { 189 return -1; 190 } 191 192 void *libgio = dlopen ("libgio-2.0.so", RTLD_LAZY | RTLD_GLOBAL); 193 wrapper_load_symbols_gio(libgio); 194 195 wrapper_loaded = 1; 196 197 return wrapper_gtk_version; 198 }