Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/UNIXToolkit.java
32287 views
/*1* Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.awt;2526import java.awt.RenderingHints;27import static java.awt.RenderingHints.*;28import java.awt.color.ColorSpace;29import java.awt.image.*;30import java.security.AccessController;31import java.security.PrivilegedAction;32import sun.security.action.GetIntegerAction;33import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection;34import sun.java2d.opengl.OGLRenderQueue;35import sun.security.action.GetPropertyAction;3637public abstract class UNIXToolkit extends SunToolkit38{39/** All calls into GTK should be synchronized on this lock */40public static final Object GTK_LOCK = new Object();4142private static final int[] BAND_OFFSETS = { 0, 1, 2 };43private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 };44private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000;4546// Allowed GTK versions47public enum GtkVersions {48ANY(0),49GTK2(Constants.GTK2_MAJOR_NUMBER),50GTK3(Constants.GTK3_MAJOR_NUMBER);5152static class Constants {53static final int GTK2_MAJOR_NUMBER = 2;54static final int GTK3_MAJOR_NUMBER = 3;55}5657final int number;5859GtkVersions(int number) {60this.number = number;61}6263public static GtkVersions getVersion(int number) {64switch (number) {65case Constants.GTK2_MAJOR_NUMBER:66return GTK2;67case Constants.GTK3_MAJOR_NUMBER:68return GTK3;69default:70return ANY;71}72}7374// major GTK version number75public int getNumber() {76return number;77}78};7980private Boolean nativeGTKAvailable;81private Boolean nativeGTKLoaded;82private BufferedImage tmpImage = null;8384public static int getDatatransferTimeout() {85Integer dt = (Integer)AccessController.doPrivileged(86new GetIntegerAction("sun.awt.datatransfer.timeout"));87if (dt == null || dt <= 0) {88return DEFAULT_DATATRANSFER_TIMEOUT;89} else {90return dt;91}92}9394/**95* Returns true if the native GTK libraries are capable of being96* loaded and are expected to work properly, false otherwise. Note97* that this method will not leave the native GTK libraries loaded if98* they haven't already been loaded. This allows, for example, Swing's99* GTK L&F to test for the presence of native GTK support without100* leaving the native libraries loaded. To attempt long-term loading101* of the native GTK libraries, use the loadGTK() method instead.102*/103@Override104public boolean isNativeGTKAvailable() {105synchronized (GTK_LOCK) {106if (nativeGTKLoaded != null) {107// We've already attempted to load GTK, so just return the108// status of that attempt.109return nativeGTKLoaded;110111} else if (nativeGTKAvailable != null) {112// We've already checked the availability of the native GTK113// libraries, so just return the status of that attempt.114return nativeGTKAvailable;115116} else {117boolean success = check_gtk(getEnabledGtkVersion().getNumber());118nativeGTKAvailable = success;119return success;120}121}122}123124/**125* Loads the GTK libraries, if necessary. The first time this method126* is called, it will attempt to load the native GTK library. If127* successful, it leaves the library open and returns true; otherwise,128* the library is left closed and returns false. On future calls to129* this method, the status of the first attempt is returned (a simple130* lightweight boolean check, no native calls required).131*/132public boolean loadGTK() {133synchronized (GTK_LOCK) {134if (nativeGTKLoaded == null) {135nativeGTKLoaded = load_gtk(getEnabledGtkVersion().getNumber(),136isGtkVerbose());137}138}139return nativeGTKLoaded;140}141142/**143* Overridden to handle GTK icon loading144*/145protected Object lazilyLoadDesktopProperty(String name) {146if (name.startsWith("gtk.icon.")) {147return lazilyLoadGTKIcon(name);148}149return super.lazilyLoadDesktopProperty(name);150}151152/**153* Load a native Gtk stock icon.154*155* @param longname a desktop property name. This contains icon name, size156* and orientation, e.g. <code>"gtk.icon.gtk-add.4.rtl"</code>157* @return an <code>Image</code> for the icon, or <code>null</code> if the158* icon could not be loaded159*/160protected Object lazilyLoadGTKIcon(String longname) {161// Check if we have already loaded it.162Object result = desktopProperties.get(longname);163if (result != null) {164return result;165}166167// We need to have at least gtk.icon.<stock_id>.<size>.<orientation>168String str[] = longname.split("\\.");169if (str.length != 5) {170return null;171}172173// Parse out the stock icon size we are looking for.174int size = 0;175try {176size = Integer.parseInt(str[3]);177} catch (NumberFormatException nfe) {178return null;179}180181// Direction.182TextDirection dir = ("ltr".equals(str[4]) ? TextDirection.LTR :183TextDirection.RTL);184185// Load the stock icon.186BufferedImage img = getStockIcon(-1, str[2], size, dir.ordinal(), null);187if (img != null) {188// Create the desktop property for the icon.189setDesktopProperty(longname, img);190}191return img;192}193194/**195* Returns a BufferedImage which contains the Gtk icon requested. If no196* such icon exists or an error occurs loading the icon the result will197* be null.198*199* @param filename200* @return The icon or null if it was not found or loaded.201*/202public BufferedImage getGTKIcon(final String filename) {203if (!loadGTK()) {204return null;205206} else {207// Call the native method to load the icon.208synchronized (GTK_LOCK) {209if (!load_gtk_icon(filename)) {210tmpImage = null;211}212}213}214// Return local image the callback loaded the icon into.215return tmpImage;216}217218/**219* Returns a BufferedImage which contains the Gtk stock icon requested.220* If no such stock icon exists the result will be null.221*222* @param widgetType one of WidgetType values defined in GTKNativeEngine or223* -1 for system default stock icon.224* @param stockId String which defines the stock id of the gtk item.225* For a complete list reference the API at www.gtk.org for StockItems.226* @param iconSize One of the GtkIconSize values defined in GTKConstants227* @param textDirection One of the TextDirection values defined in228* GTKConstants229* @param detail Render detail that is passed to the native engine (feel230* free to pass null)231* @return The stock icon or null if it was not found or loaded.232*/233public BufferedImage getStockIcon(final int widgetType, final String stockId,234final int iconSize, final int direction,235final String detail) {236if (!loadGTK()) {237return null;238239} else {240// Call the native method to load the icon.241synchronized (GTK_LOCK) {242if (!load_stock_icon(widgetType, stockId, iconSize, direction, detail)) {243tmpImage = null;244}245}246}247// Return local image the callback loaded the icon into.248return tmpImage; // set by loadIconCallback249}250251/**252* This method is used by JNI as a callback from load_stock_icon.253* Image data is passed back to us via this method and loaded into the254* local BufferedImage and then returned via getStockIcon.255*256* Do NOT call this method directly.257*/258public void loadIconCallback(byte[] data, int width, int height,259int rowStride, int bps, int channels, boolean alpha) {260// Reset the stock image to null.261tmpImage = null;262263// Create a new BufferedImage based on the data returned from the264// JNI call.265DataBuffer dataBuf = new DataBufferByte(data, (rowStride * height));266// Maybe test # channels to determine band offsets?267WritableRaster raster = Raster.createInterleavedRaster(dataBuf,268width, height, rowStride, channels,269(alpha ? BAND_OFFSETS_ALPHA : BAND_OFFSETS), null);270ColorModel colorModel = new ComponentColorModel(271ColorSpace.getInstance(ColorSpace.CS_sRGB), alpha, false,272ColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);273274// Set the local image so we can return it later from275// getStockIcon().276tmpImage = new BufferedImage(colorModel, raster, false, null);277}278279private static native boolean check_gtk(int version);280private static native boolean load_gtk(int version, boolean verbose);281private static native boolean unload_gtk();282private native boolean load_gtk_icon(String filename);283private native boolean load_stock_icon(int widget_type, String stock_id,284int iconSize, int textDirection, String detail);285286private native void nativeSync();287private static native int get_gtk_version();288289@Override290public void sync() {291// flush the X11 buffer292nativeSync();293// now flush the OGL pipeline (this is a no-op if OGL is not enabled)294OGLRenderQueue.sync();295}296297/*298* This returns the value for the desktop property "awt.font.desktophints"299* It builds this by querying the Gnome desktop properties to return300* them as platform independent hints.301* This requires that the Gnome properties have already been gathered.302*/303public static final String FONTCONFIGAAHINT = "fontconfig/Antialias";304305@Override306protected RenderingHints getDesktopAAHints() {307308Object aaValue = getDesktopProperty("gnome.Xft/Antialias");309310if (aaValue == null) {311/* On a KDE desktop running KWin the rendering hint will312* have been set as property "fontconfig/Antialias".313* No need to parse further in this case.314*/315aaValue = getDesktopProperty(FONTCONFIGAAHINT);316if (aaValue != null) {317return new RenderingHints(KEY_TEXT_ANTIALIASING, aaValue);318} else {319return null; // no Gnome or KDE Desktop properties available.320}321}322323/* 0 means off, 1 means some ON. What would any other value mean?324* If we require "1" to enable AA then some new value would cause325* us to default to "OFF". I don't think that's the best guess.326* So if its !=0 then lets assume AA.327*/328boolean aa = ((aaValue instanceof Number)329&& ((Number) aaValue).intValue() != 0);330Object aaHint;331if (aa) {332String subpixOrder =333(String)getDesktopProperty("gnome.Xft/RGBA");334335if (subpixOrder == null || subpixOrder.equals("none")) {336aaHint = VALUE_TEXT_ANTIALIAS_ON;337} else if (subpixOrder.equals("rgb")) {338aaHint = VALUE_TEXT_ANTIALIAS_LCD_HRGB;339} else if (subpixOrder.equals("bgr")) {340aaHint = VALUE_TEXT_ANTIALIAS_LCD_HBGR;341} else if (subpixOrder.equals("vrgb")) {342aaHint = VALUE_TEXT_ANTIALIAS_LCD_VRGB;343} else if (subpixOrder.equals("vbgr")) {344aaHint = VALUE_TEXT_ANTIALIAS_LCD_VBGR;345} else {346/* didn't recognise the string, but AA is requested */347aaHint = VALUE_TEXT_ANTIALIAS_ON;348}349} else {350aaHint = VALUE_TEXT_ANTIALIAS_DEFAULT;351}352return new RenderingHints(KEY_TEXT_ANTIALIASING, aaHint);353}354355private native boolean gtkCheckVersionImpl(int major, int minor,356int micro);357358/**359* Returns {@code true} if the GTK+ library is compatible with the given360* version.361*362* @param major363* The required major version.364* @param minor365* The required minor version.366* @param micro367* The required micro version.368* @return {@code true} if the GTK+ library is compatible with the given369* version.370*/371public boolean checkGtkVersion(int major, int minor, int micro) {372if (loadGTK()) {373return gtkCheckVersionImpl(major, minor, micro);374}375return false;376}377378public static GtkVersions getEnabledGtkVersion() {379String version = AccessController.doPrivileged(380new GetPropertyAction("jdk.gtk.version"));381if (version == null) {382return GtkVersions.ANY;383} else if (version.startsWith("2")) {384return GtkVersions.GTK2;385} else if("3".equals(version) ){386return GtkVersions.GTK3;387}388return GtkVersions.ANY;389}390391public static GtkVersions getGtkVersion() {392return GtkVersions.getVersion(get_gtk_version());393}394395public static boolean isGtkVerbose() {396return AccessController.doPrivileged((PrivilegedAction<Boolean>)()397-> Boolean.getBoolean("jdk.gtk.verbose"));398}399}400401402