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
30GtkApi* gtk2_load(JNIEnv *env, const char* lib_name);
31GtkApi* gtk3_load(JNIEnv *env, const char* lib_name);
32
33gboolean gtk2_check(const char* lib_name, gboolean load);
34gboolean gtk3_check(const char* lib_name, gboolean load);
35
36GtkApi *gtk;
37
38typedef 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
46static GtkLib gtk_libs[] = {
47 {
48 GTK_3,
49 JNI_LIB_NAME("gtk-3"),
50 VERSIONED_JNI_LIB_NAME("gtk-3", "0"),
51 &gtk3_load,
52 &gtk3_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 &gtk2_load,
59 &gtk2_check
60 }
61};
62
63static 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] = &gtk_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] = &gtk_libs[first];
82 }
83 return load_order;
84}
85
86static 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
100gboolean 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
142static 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
156gboolean gtk_check_version(GtkVersion version) {
157 if (gtk || get_loaded()) {
158 return TRUE;
159 }
160 return check_version(version);
161}
162
163