--- old/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c 2016-05-26 13:45:41.634241428 +0300 +++ new/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c 2016-05-26 13:45:41.522241432 +0300 @@ -43,7 +43,7 @@ gboolean (*check)(const char* lib_name, gboolean load); } GtkLib; -static GtkLib libs[] = { +static GtkLib gtk_libs[] = { { GTK_2, JNI_LIB_NAME("gtk-x11-2.0"), @@ -57,26 +57,43 @@ VERSIONED_JNI_LIB_NAME("gtk-3", "0"), >k3_load, >k3_check - }, - { - 0, - NULL, - NULL, - NULL, - NULL } }; +static GtkLib** get_libs_order(GtkVersion version) { + static GtkLib** load_order; + static int n_libs = 0; + if (!n_libs) { + n_libs = sizeof(gtk_libs) / sizeof(GtkLib); + load_order = malloc(1 + n_libs * sizeof(GtkLib *)); + load_order[n_libs] = 0; + } + int i, first = 0; + for (i = 0; i < n_libs; i++) { + load_order[i] = >k_libs[i]; + if (load_order[i]->version == version) { + first = i; + } + } + if (first) { + for (i = first; i > 0; i--) { + load_order[i] = load_order[i - 1]; + } + load_order[0] = >k_libs[first]; + } + return load_order; +} + static GtkLib* get_loaded() { - GtkLib* lib = libs; - while(!gtk && lib->version) { + GtkLib** libs = get_libs_order(GTK_ANY); + while(!gtk && *libs) { + GtkLib* lib = *libs++; if (lib->check(lib->vname, /* load = */FALSE)) { return lib; } if (lib->check(lib->name, /* load = */FALSE)) { return lib; } - lib++; } return NULL; } @@ -85,23 +102,18 @@ if (gtk == NULL) { GtkLib* lib = get_loaded(); if (lib) { - if (version != GTK_ANY && lib->version != version) { - if (verbose) { - fprintf(stderr, "WARNING: Cannot load GTK%d library: \ - GTK%d has already been loaded\n", version, lib->version); - } - return FALSE; - } if (verbose) { - fprintf(stderr, "Looking for GTK%d library...\n", version); + fprintf(stderr, "Looking for GTK%d library...\n", + lib->version); } gtk = lib->load(env, lib->vname); if (!gtk) { gtk = lib->load(env, lib->name); } } else { - lib = libs; - while (!gtk && lib->version) { + GtkLib** libs = get_libs_order(version); + while (!gtk && *libs) { + lib = *libs++; if (version == GTK_ANY || lib->version == version) { if (verbose) { fprintf(stderr, "Looking for GTK%d library...\n", @@ -115,9 +127,7 @@ fprintf(stderr, "Not found.\n"); } } - lib++; } - lib--; } if (verbose) { if (gtk) { @@ -131,17 +141,15 @@ } static gboolean check_version(GtkVersion version) { - GtkLib* lib = libs; - while (lib->version) { - if (version == GTK_ANY || lib->version == version) { - if (lib->check(lib->vname, /* load = */TRUE)) { - return TRUE; - } - if (lib->check(lib->name, /* load = */TRUE)) { - return TRUE; - } + GtkLib** libs = get_libs_order(GTK_ANY); + while (*libs) { + GtkLib* lib = *libs++; + if (lib->check(lib->vname, /* load = */TRUE)) { + return TRUE; + } + if (lib->check(lib->name, /* load = */TRUE)) { + return TRUE; } - lib++; } return FALSE; } --- /dev/null 2016-05-25 16:51:37.820917969 +0300 +++ new/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java 2016-05-26 13:45:41.794241423 +0300 @@ -0,0 +1,78 @@ +/* + * 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. + * + * 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. + */ + +/* @test + * @bug 8156121 + * @summary "Fail forward" fails for GTK3 if no GTK2 available + * @modules java.desktop/sun.awt + * @requires (os.family == "linux") + * @run main GtkVersionTest + */ + +import sun.awt.UNIXToolkit; + +import java.awt.*; +import java.io.*; + +public class GtkVersionTest { + public static class LoadGtk { + public static void main(String[] args) { + ((UNIXToolkit)Toolkit.getDefaultToolkit()).loadGTK(); + } + } + + public static void main(String[] args) throws Exception { + test(null, "2"); + test("2", "2"); + test("2.2", "2"); + test("3", "3"); + } + + private static void test(String version, String expect) throws Exception { + System.out.println( "Test " + + (version == null ? "no" : " GTK" + version) + " preference."); + Process p = Runtime.getRuntime().exec(System.getProperty("java.home") + + "/bin/java " + + (version == null ? "" : "-Djdk.gtk.version=" + version) + + " -Djdk.gtk.verbose=true " + + "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED " + + "-cp " + System.getProperty("java.class.path", ".") + + " GtkVersionTest$LoadGtk"); + p.waitFor(); + + try (BufferedReader br = new BufferedReader( + new InputStreamReader(p.getErrorStream()))) { + String line; + while ((line = br.readLine()) != null) { + System.out.println(line); + if (line.contains("Looking for GTK" + expect + " library")) { + return; + } else if (line.contains("Looking for GTK")) { + break; + } + } + throw new RuntimeException("Wrong GTK library version: \n" + line); + } + } + +}