1 | /* |
2 | * Copyright (c) 2005, 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 | #include <dlfcn.h> |
26 | #include <stdlib.h> |
27 | #include "jvm_md.h" |
28 | #include "gtk_interface.h" |
29 | |
30 | GtkApi* gtk2_load(JNIEnv *env, const char* lib_name); |
31 | GtkApi* gtk3_load(JNIEnv *env, const char* lib_name); |
32 | |
33 | gboolean gtk2_check(const char* lib_name, gboolean load); |
34 | gboolean gtk3_check(const char* lib_name, gboolean load); |
35 | |
36 | GtkApi *gtk; |
37 | |
38 | typedef struct { |
39 | GtkVersion version; |
40 | const char* name; |
41 | const char* vname; |
42 | GtkApi* (*load)(JNIEnv *env, const char* lib_name); |
43 | gboolean (*check)(const char* lib_name, gboolean load); |
44 | } GtkLib; |
45 | |
46 | static GtkLib gtk_libs[] = { |
47 | { |
48 | GTK_3, |
49 | JNI_LIB_NAME("gtk-3" ), |
50 | VERSIONED_JNI_LIB_NAME("gtk-3" , "0" ), |
51 | >k3_load, |
52 | >k3_check |
53 | }, |
54 | { |
55 | GTK_2, |
56 | JNI_LIB_NAME("gtk-x11-2.0" ), |
57 | VERSIONED_JNI_LIB_NAME("gtk-x11-2.0" , "0" ), |
58 | >k2_load, |
59 | >k2_check |
60 | } |
61 | }; |
62 | |
63 | static GtkLib** get_libs_order(GtkVersion version) { |
64 | static GtkLib** load_order; |
65 | static int n_libs = 0; |
66 | if (!n_libs) { |
67 | n_libs = sizeof(gtk_libs) / sizeof(GtkLib); |
68 | load_order = calloc(n_libs + 1, sizeof(GtkLib *)); |
69 | } |
70 | int i, first = 0; |
71 | for (i = 0; i < n_libs; i++) { |
72 | load_order[i] = >k_libs[i]; |
73 | if (load_order[i]->version == version) { |
74 | first = i; |
75 | } |
76 | } |
77 | if (first) { |
78 | for (i = first; i > 0; i--) { |
79 | load_order[i] = load_order[i - 1]; |
80 | } |
81 | load_order[0] = >k_libs[first]; |
82 | } |
83 | return load_order; |
84 | } |
85 | |
86 | static GtkLib* get_loaded() { |
87 | GtkLib** libs = get_libs_order(GTK_ANY); |
88 | while(!gtk && *libs) { |
89 | GtkLib* lib = *libs++; |
90 | if (lib->check(lib->vname, /* load = */FALSE)) { |
91 | return lib; |
92 | } |
93 | if (lib->check(lib->name, /* load = */FALSE)) { |
94 | return lib; |
95 | } |
96 | } |
97 | return NULL; |
98 | } |
99 | |
100 | gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose) { |
101 | if (gtk == NULL) { |
102 | GtkLib* lib = get_loaded(); |
103 | if (lib) { |
104 | if (verbose) { |
105 | fprintf(stderr, "Looking for GTK%d library...\n" , |
106 | lib->version); |
107 | } |
108 | gtk = lib->load(env, lib->vname); |
109 | if (!gtk) { |
110 | gtk = lib->load(env, lib->name); |
111 | } |
112 | } else { |
113 | GtkLib** libs = get_libs_order(version); |
114 | while (!gtk && *libs) { |
115 | lib = *libs++; |
116 | if (version == GTK_ANY || lib->version == version) { |
117 | if (verbose) { |
118 | fprintf(stderr, "Looking for GTK%d library...\n" , |
119 | lib->version); |
120 | } |
121 | gtk = lib->load(env, lib->vname); |
122 | if (!gtk) { |
123 | gtk = lib->load(env, lib->name); |
124 | } |
125 | if (verbose && !gtk) { |
126 | fprintf(stderr, "Not found.\n" ); |
127 | } |
128 | } |
129 | } |
130 | } |
131 | if (verbose) { |
132 | if (gtk) { |
133 | fprintf(stderr, "GTK%d library loaded.\n" , lib->version); |
134 | } else { |
135 | fprintf(stderr, "Failed to load GTK library.\n" ); |
136 | } |
137 | } |
138 | } |
139 | return gtk != NULL; |
140 | } |
141 | |
142 | static gboolean check_version(GtkVersion version) { |
143 | GtkLib** libs = get_libs_order(version); |
144 | while (*libs) { |
145 | GtkLib* lib = *libs++; |
146 | if (lib->check(lib->vname, /* load = */TRUE)) { |
147 | return TRUE; |
148 | } |
149 | if (lib->check(lib->name, /* load = */TRUE)) { |
150 | return TRUE; |
151 | } |
152 | } |
153 | return FALSE; |
154 | } |
155 | |
156 | gboolean gtk_check_version(GtkVersion version) { |
157 | if (gtk || get_loaded()) { |
158 | return TRUE; |
159 | } |
160 | return check_version(version); |
161 | } |
162 | |
163 | |