Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java
41152 views
/*1* Copyright (c) 1997, 2021, 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*/2425package sun.awt;2627import java.awt.AWTError;28import java.awt.GraphicsDevice;29import java.lang.ref.WeakReference;30import java.net.InetAddress;31import java.net.NetworkInterface;32import java.net.SocketException;33import java.net.UnknownHostException;34import java.util.ArrayList;35import java.util.Enumeration;36import java.util.HashMap;37import java.util.List;38import java.util.ListIterator;39import java.util.Map;4041import sun.awt.X11.XToolkit;42import sun.java2d.SunGraphicsEnvironment;43import sun.java2d.SurfaceManagerFactory;44import sun.java2d.UnixSurfaceManagerFactory;45import sun.java2d.xr.XRSurfaceData;4647/**48* This is an implementation of a GraphicsEnvironment object for the49* default local GraphicsEnvironment used by the Java Runtime Environment50* for X11 environments.51*52* @see GraphicsDevice53* @see java.awt.GraphicsConfiguration54*/55@SuppressWarnings("removal")56public final class X11GraphicsEnvironment extends SunGraphicsEnvironment {5758static {59java.security.AccessController.doPrivileged(60new java.security.PrivilegedAction<Object>() {61public Object run() {62System.loadLibrary("awt");6364/*65* Note: The MToolkit object depends on the static initializer66* of X11GraphicsEnvironment to initialize the connection to67* the X11 server.68*/69if (!isHeadless()) {70// first check the OGL system property71boolean glxRequested = false;72String prop = System.getProperty("sun.java2d.opengl");73if (prop != null) {74if (prop.equals("true") || prop.equals("t")) {75glxRequested = true;76} else if (prop.equals("True") || prop.equals("T")) {77glxRequested = true;78glxVerbose = true;79}80}8182// Now check for XRender system property83boolean xRenderRequested = true;84boolean xRenderIgnoreLinuxVersion = false;85String xProp = System.getProperty("sun.java2d.xrender");86if (xProp != null) {87if (xProp.equals("false") || xProp.equals("f")) {88xRenderRequested = false;89} else if (xProp.equals("True") || xProp.equals("T")) {90xRenderRequested = true;91xRenderVerbose = true;92}9394if(xProp.equalsIgnoreCase("t") || xProp.equalsIgnoreCase("true")) {95xRenderIgnoreLinuxVersion = true;96}97}9899// initialize the X11 display connection100initDisplay(glxRequested);101102// only attempt to initialize GLX if it was requested103if (glxRequested) {104glxAvailable = initGLX();105if (glxVerbose && !glxAvailable) {106System.out.println(107"Could not enable OpenGL " +108"pipeline (GLX 1.3 not available)");109}110}111112// only attempt to initialize Xrender if it was requested113if (xRenderRequested) {114xRenderAvailable = initXRender(xRenderVerbose, xRenderIgnoreLinuxVersion);115if (xRenderVerbose && !xRenderAvailable) {116System.out.println(117"Could not enable XRender pipeline");118}119}120121if (xRenderAvailable) {122XRSurfaceData.initXRSurfaceData();123}124}125126return null;127}128});129130// Install the correct surface manager factory.131SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory());132133}134135136private static boolean glxAvailable;137private static boolean glxVerbose;138139private static native boolean initGLX();140141public static boolean isGLXAvailable() {142return glxAvailable;143}144145public static boolean isGLXVerbose() {146return glxVerbose;147}148149private static boolean xRenderVerbose;150private static boolean xRenderAvailable;151152private static native boolean initXRender(boolean verbose, boolean ignoreLinuxVersion);153public static boolean isXRenderAvailable() {154return xRenderAvailable;155}156157public static boolean isXRenderVerbose() {158return xRenderVerbose;159}160161/**162* Checks if Shared Memory extension can be used.163* Returns:164* -1 if server doesn't support MITShm165* 1 if server supports it and it can be used166* 0 otherwise167*/168private static native int checkShmExt();169170private static native String getDisplayString();171private Boolean isDisplayLocal;172173/** Available X11 screens. */174private final Map<Integer, X11GraphicsDevice> devices = new HashMap<>(5);175176/**177* The key in the {@link #devices} for the main screen.178*/179private int mainScreen;180181// list of invalidated graphics devices (those which were removed)182private List<WeakReference<X11GraphicsDevice>> oldDevices = new ArrayList<>();183184/**185* This should only be called from the static initializer, so no need for186* the synchronized keyword.187*/188private static native void initDisplay(boolean glxRequested);189190protected native int getNumScreens();191192private native int getDefaultScreenNum();193194public X11GraphicsEnvironment() {195if (isHeadless()) {196return;197}198199/* Populate the device table */200rebuildDevices();201}202203/**204* Initialize the native list of devices.205*/206private static native void initNativeData();207208/**209* Updates the list of devices and notify listeners.210*/211public void rebuildDevices() {212XToolkit.awtLock();213try {214initNativeData();215initDevices();216} finally {217XToolkit.awtUnlock();218}219displayChanged();220}221222/**223* (Re)create all X11GraphicsDevices, reuses a devices if it is possible.224*/225private synchronized void initDevices() {226Map<Integer, X11GraphicsDevice> old = new HashMap<>(devices);227devices.clear();228229int numScreens = getNumScreens();230if (numScreens == 0) {231throw new AWTError("no screen devices");232}233int index = getDefaultScreenNum();234mainScreen = 0 < index && index < screens.length ? index : 0;235236for (int id = 0; id < numScreens; ++id) {237devices.put(id, old.containsKey(id) ? old.remove(id) :238new X11GraphicsDevice(id));239}240// if a device was not reused it should be invalidated241for (X11GraphicsDevice gd : old.values()) {242oldDevices.add(new WeakReference<>(gd));243}244// Need to notify old devices, in case the user hold the reference to it245for (ListIterator<WeakReference<X11GraphicsDevice>> it =246oldDevices.listIterator(); it.hasNext(); ) {247X11GraphicsDevice gd = it.next().get();248if (gd != null) {249gd.invalidate(devices.get(mainScreen));250gd.displayChanged();251} else {252// no more references to this device, remove it253it.remove();254}255}256}257258@Override259public synchronized GraphicsDevice getDefaultScreenDevice() {260return devices.get(mainScreen);261}262263@Override264public synchronized GraphicsDevice[] getScreenDevices() {265return devices.values().toArray(new X11GraphicsDevice[0]);266}267268public synchronized GraphicsDevice getScreenDevice(int screen) {269return devices.get(screen);270}271272@Override273protected GraphicsDevice makeScreenDevice(int screennum) {274throw new UnsupportedOperationException("This method is unused and" +275"should not be called in this implementation");276}277278public boolean isDisplayLocal() {279if (isDisplayLocal == null) {280SunToolkit.awtLock();281try {282if (isDisplayLocal == null) {283isDisplayLocal = Boolean.valueOf(_isDisplayLocal());284}285} finally {286SunToolkit.awtUnlock();287}288}289return isDisplayLocal.booleanValue();290}291292private static boolean _isDisplayLocal() {293if (isHeadless()) {294return true;295}296297String isRemote = java.security.AccessController.doPrivileged(298new sun.security.action.GetPropertyAction("sun.java2d.remote"));299if (isRemote != null) {300return isRemote.equals("false");301}302303int shm = checkShmExt();304if (shm != -1) {305return (shm == 1);306}307308// If XServer doesn't support ShMem extension,309// try the other way310311String display = getDisplayString();312int ind = display.indexOf(':');313final String hostName = display.substring(0, ind);314if (ind <= 0) {315// ':0' case316return true;317}318319Boolean result = java.security.AccessController.doPrivileged(320new java.security.PrivilegedAction<Boolean>() {321public Boolean run() {322InetAddress[] remAddr = null;323Enumeration<InetAddress> locals = null;324Enumeration<NetworkInterface> interfaces = null;325try {326interfaces = NetworkInterface.getNetworkInterfaces();327remAddr = InetAddress.getAllByName(hostName);328if (remAddr == null) {329return Boolean.FALSE;330}331} catch (UnknownHostException e) {332System.err.println("Unknown host: " + hostName);333return Boolean.FALSE;334} catch (SocketException e1) {335System.err.println(e1.getMessage());336return Boolean.FALSE;337}338339for (; interfaces.hasMoreElements();) {340locals = interfaces.nextElement().getInetAddresses();341for (; locals.hasMoreElements();) {342final InetAddress localAddr = locals.nextElement();343for (int i = 0; i < remAddr.length; i++) {344if (localAddr.equals(remAddr[i])) {345return Boolean.TRUE;346}347}348}349}350return Boolean.FALSE;351}});352return result.booleanValue();353}354355356357/**358* Returns face name for default font, or null if359* no face names are used for CompositeFontDescriptors360* for this platform.361*/362public String getDefaultFontFaceName() {363364return null;365}366367private static native boolean pRunningXinerama();368369public boolean runningXinerama() {370return pRunningXinerama();371}372373/**374* From the DisplayChangedListener interface; devices do not need375* to react to this event.376*/377@Override378public void paletteChanged() {379}380}381382383