/*
* Copyright (c) 1997, 2021, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt;
import java.awt.AWTError;
import java.awt.GraphicsDevice;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import sun.awt.X11.XToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceManagerFactory;
import sun.java2d.UnixSurfaceManagerFactory;
import sun.java2d.xr.XRSurfaceData;
This is an implementation of a GraphicsEnvironment object for the
default local GraphicsEnvironment used by the Java Runtime Environment
for X11 environments.
See Also: - GraphicsDevice
- GraphicsConfiguration
/**
* This is an implementation of a GraphicsEnvironment object for the
* default local GraphicsEnvironment used by the Java Runtime Environment
* for X11 environments.
*
* @see GraphicsDevice
* @see java.awt.GraphicsConfiguration
*/
public final class X11GraphicsEnvironment extends SunGraphicsEnvironment {
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Object>() {
public Object run() {
System.loadLibrary("awt");
/*
* Note: The MToolkit object depends on the static initializer
* of X11GraphicsEnvironment to initialize the connection to
* the X11 server.
*/
if (!isHeadless()) {
// first check the OGL system property
boolean glxRequested = false;
String prop = System.getProperty("sun.java2d.opengl");
if (prop != null) {
if (prop.equals("true") || prop.equals("t")) {
glxRequested = true;
} else if (prop.equals("True") || prop.equals("T")) {
glxRequested = true;
glxVerbose = true;
}
}
// Now check for XRender system property
boolean xRenderRequested = true;
boolean xRenderIgnoreLinuxVersion = false;
String xProp = System.getProperty("sun.java2d.xrender");
if (xProp != null) {
if (xProp.equals("false") || xProp.equals("f")) {
xRenderRequested = false;
} else if (xProp.equals("True") || xProp.equals("T")) {
xRenderRequested = true;
xRenderVerbose = true;
}
if(xProp.equalsIgnoreCase("t") || xProp.equalsIgnoreCase("true")) {
xRenderIgnoreLinuxVersion = true;
}
}
// initialize the X11 display connection
initDisplay(glxRequested);
// only attempt to initialize GLX if it was requested
if (glxRequested) {
glxAvailable = initGLX();
if (glxVerbose && !glxAvailable) {
System.out.println(
"Could not enable OpenGL " +
"pipeline (GLX 1.3 not available)");
}
}
// only attempt to initialize Xrender if it was requested
if (xRenderRequested) {
xRenderAvailable = initXRender(xRenderVerbose, xRenderIgnoreLinuxVersion);
if (xRenderVerbose && !xRenderAvailable) {
System.out.println(
"Could not enable XRender pipeline");
}
}
if (xRenderAvailable) {
XRSurfaceData.initXRSurfaceData();
}
}
return null;
}
});
// Install the correct surface manager factory.
SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory());
}
private static boolean glxAvailable;
private static boolean glxVerbose;
private static native boolean initGLX();
public static boolean isGLXAvailable() {
return glxAvailable;
}
public static boolean isGLXVerbose() {
return glxVerbose;
}
private static boolean xRenderVerbose;
private static boolean xRenderAvailable;
private static native boolean initXRender(boolean verbose, boolean ignoreLinuxVersion);
public static boolean isXRenderAvailable() {
return xRenderAvailable;
}
public static boolean isXRenderVerbose() {
return xRenderVerbose;
}
Checks if Shared Memory extension can be used.
Returns:
-1 if server doesn't support MITShm
1 if server supports it and it can be used
0 otherwise
/**
* Checks if Shared Memory extension can be used.
* Returns:
* -1 if server doesn't support MITShm
* 1 if server supports it and it can be used
* 0 otherwise
*/
private static native int checkShmExt();
private static native String getDisplayString();
private Boolean isDisplayLocal;
Available X11 screens. /** Available X11 screens. */
private final Map<Integer, X11GraphicsDevice> devices = new HashMap<>(5);
The key in the devices
for the main screen. /**
* The key in the {@link #devices} for the main screen.
*/
private int mainScreen;
// list of invalidated graphics devices (those which were removed)
private List<WeakReference<X11GraphicsDevice>> oldDevices = new ArrayList<>();
This should only be called from the static initializer, so no need for
the synchronized keyword.
/**
* This should only be called from the static initializer, so no need for
* the synchronized keyword.
*/
private static native void initDisplay(boolean glxRequested);
protected native int getNumScreens();
private native int getDefaultScreenNum();
public X11GraphicsEnvironment() {
if (isHeadless()) {
return;
}
/* Populate the device table */
rebuildDevices();
}
Initialize the native list of devices.
/**
* Initialize the native list of devices.
*/
private static native void initNativeData();
Updates the list of devices and notify listeners.
/**
* Updates the list of devices and notify listeners.
*/
public void rebuildDevices() {
XToolkit.awtLock();
try {
initNativeData();
initDevices();
} finally {
XToolkit.awtUnlock();
}
displayChanged();
}
(Re)create all X11GraphicsDevices, reuses a devices if it is possible.
/**
* (Re)create all X11GraphicsDevices, reuses a devices if it is possible.
*/
private synchronized void initDevices() {
Map<Integer, X11GraphicsDevice> old = new HashMap<>(devices);
devices.clear();
int numScreens = getNumScreens();
if (numScreens == 0) {
throw new AWTError("no screen devices");
}
int index = getDefaultScreenNum();
mainScreen = 0 < index && index < screens.length ? index : 0;
for (int id = 0; id < numScreens; ++id) {
devices.put(id, old.containsKey(id) ? old.remove(id) :
new X11GraphicsDevice(id));
}
// if a device was not reused it should be invalidated
for (X11GraphicsDevice gd : old.values()) {
oldDevices.add(new WeakReference<>(gd));
}
// Need to notify old devices, in case the user hold the reference to it
for (ListIterator<WeakReference<X11GraphicsDevice>> it =
oldDevices.listIterator(); it.hasNext(); ) {
X11GraphicsDevice gd = it.next().get();
if (gd != null) {
gd.invalidate(devices.get(mainScreen));
gd.displayChanged();
} else {
// no more references to this device, remove it
it.remove();
}
}
}
@Override
public synchronized GraphicsDevice getDefaultScreenDevice() {
return devices.get(mainScreen);
}
@Override
public synchronized GraphicsDevice[] getScreenDevices() {
return devices.values().toArray(new X11GraphicsDevice[0]);
}
public synchronized GraphicsDevice getScreenDevice(int screen) {
return devices.get(screen);
}
@Override
protected GraphicsDevice makeScreenDevice(int screennum) {
throw new UnsupportedOperationException("This method is unused and" +
"should not be called in this implementation");
}
public boolean isDisplayLocal() {
if (isDisplayLocal == null) {
SunToolkit.awtLock();
try {
if (isDisplayLocal == null) {
isDisplayLocal = Boolean.valueOf(_isDisplayLocal());
}
} finally {
SunToolkit.awtUnlock();
}
}
return isDisplayLocal.booleanValue();
}
private static boolean _isDisplayLocal() {
if (isHeadless()) {
return true;
}
String isRemote = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.java2d.remote"));
if (isRemote != null) {
return isRemote.equals("false");
}
int shm = checkShmExt();
if (shm != -1) {
return (shm == 1);
}
// If XServer doesn't support ShMem extension,
// try the other way
String display = getDisplayString();
int ind = display.indexOf(':');
final String hostName = display.substring(0, ind);
if (ind <= 0) {
// ':0' case
return true;
}
Boolean result = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Boolean>() {
public Boolean run() {
InetAddress[] remAddr = null;
Enumeration<InetAddress> locals = null;
Enumeration<NetworkInterface> interfaces = null;
try {
interfaces = NetworkInterface.getNetworkInterfaces();
remAddr = InetAddress.getAllByName(hostName);
if (remAddr == null) {
return Boolean.FALSE;
}
} catch (UnknownHostException e) {
System.err.println("Unknown host: " + hostName);
return Boolean.FALSE;
} catch (SocketException e1) {
System.err.println(e1.getMessage());
return Boolean.FALSE;
}
for (; interfaces.hasMoreElements();) {
locals = interfaces.nextElement().getInetAddresses();
for (; locals.hasMoreElements();) {
final InetAddress localAddr = locals.nextElement();
for (int i = 0; i < remAddr.length; i++) {
if (localAddr.equals(remAddr[i])) {
return Boolean.TRUE;
}
}
}
}
return Boolean.FALSE;
}});
return result.booleanValue();
}
Returns face name for default font, or null if
no face names are used for CompositeFontDescriptors
for this platform.
/**
* Returns face name for default font, or null if
* no face names are used for CompositeFontDescriptors
* for this platform.
*/
public String getDefaultFontFaceName() {
return null;
}
private static native boolean pRunningXinerama();
public boolean runningXinerama() {
return pRunningXinerama();
}
From the DisplayChangedListener interface; devices do not need
to react to this event.
/**
* From the DisplayChangedListener interface; devices do not need
* to react to this event.
*/
@Override
public void paletteChanged() {
}
}