| /* |
| * Copyright (c) 1997, 2008, 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.GraphicsDevice; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileReader; |
| import java.io.FileNotFoundException; |
| import java.io.InputStream; |
| import java.io.IOException; |
| import java.io.StreamTokenizer; |
| import java.net.InetAddress; |
| import java.net.NetworkInterface; |
| import java.net.SocketException; |
| import java.net.UnknownHostException; |
| |
| import java.util.*; |
| |
| import sun.awt.motif.MFontConfiguration; |
| import sun.font.FcFontConfiguration; |
| import sun.font.Font2D; |
| import sun.font.FontManager; |
| import sun.font.NativeFont; |
| import sun.java2d.SunGraphicsEnvironment; |
| import sun.java2d.SurfaceManagerFactory; |
| import sun.java2d.UnixSurfaceManagerFactory; |
| import sun.util.logging.PlatformLogger; |
| |
| /** |
| * 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 GraphicsConfiguration |
| */ |
| public class X11GraphicsEnvironment |
| extends SunGraphicsEnvironment |
| { |
| private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11GraphicsEnvironment"); |
| private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.screen.X11GraphicsEnvironment"); |
| |
| private static Boolean xinerState; |
| |
| static { |
| java.security.AccessController.doPrivileged( |
| new java.security.PrivilegedAction() { |
| 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; |
| } |
| } |
| |
| // 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)"); |
| } |
| } |
| } |
| |
| 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; |
| } |
| |
| /** |
| * 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; |
| |
| /** |
| * This should only be called from the static initializer, so no need for |
| * the synchronized keyword. |
| */ |
| private static native void initDisplay(boolean glxRequested); |
| |
| public X11GraphicsEnvironment() { |
| } |
| |
| protected native int getNumScreens(); |
| |
| protected GraphicsDevice makeScreenDevice(int screennum) { |
| return new X11GraphicsDevice(screennum); |
| } |
| |
| protected native int getDefaultScreenNum(); |
| /** |
| * Returns the default screen graphics device. |
| */ |
| public GraphicsDevice getDefaultScreenDevice() { |
| return getScreenDevices()[getDefaultScreenNum()]; |
| } |
| |
| 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 = (String)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 = (Boolean)java.security.AccessController.doPrivileged( |
| new java.security.PrivilegedAction() { |
| public Object run() { |
| InetAddress remAddr[] = null; |
| Enumeration locals = null; |
| Enumeration 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 = ((NetworkInterface)interfaces.nextElement()).getInetAddresses(); |
| for (; locals.hasMoreElements();) { |
| for (int i = 0; i < remAddr.length; i++) { |
| if (locals.nextElement().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. |
| */ |
| public String getDefaultFontFaceName() { |
| |
| return null; |
| } |
| |
| private static native boolean pRunningXinerama(); |
| private static native Point getXineramaCenterPoint(); |
| |
| /** |
| * Override for Xinerama case: call new Solaris API for getting the correct |
| * centering point from the windowing system. |
| */ |
| public Point getCenterPoint() { |
| if (runningXinerama()) { |
| Point p = getXineramaCenterPoint(); |
| if (p != null) { |
| return p; |
| } |
| } |
| return super.getCenterPoint(); |
| } |
| |
| /** |
| * Override for Xinerama case |
| */ |
| public Rectangle getMaximumWindowBounds() { |
| if (runningXinerama()) { |
| return getXineramaWindowBounds(); |
| } else { |
| return super.getMaximumWindowBounds(); |
| } |
| } |
| |
| public boolean runningXinerama() { |
| if (xinerState == null) { |
| // pRunningXinerama() simply returns a global boolean variable, |
| // so there is no need to synchronize here |
| xinerState = Boolean.valueOf(pRunningXinerama()); |
| if (screenLog.isLoggable(PlatformLogger.FINER)) { |
| screenLog.finer("Running Xinerama: " + xinerState); |
| } |
| } |
| return xinerState.booleanValue(); |
| } |
| |
| /** |
| * Return the bounds for a centered Window on a system running in Xinerama |
| * mode. |
| * |
| * Calculations are based on the assumption of a perfectly rectangular |
| * display area (display edges line up with one another, and displays |
| * have consistent width and/or height). |
| * |
| * The bounds to return depend on the arrangement of displays and on where |
| * Windows are to be centered. There are two common situations: |
| * |
| * 1) The center point lies at the center of the combined area of all the |
| * displays. In this case, the combined area of all displays is |
| * returned. |
| * |
| * 2) The center point lies at the center of a single display. In this case |
| * the user most likely wants centered Windows to be constrained to that |
| * single display. The boundaries of the one display are returned. |
| * |
| * It is possible for the center point to be at both the center of the |
| * entire display space AND at the center of a single monitor (a square of |
| * 9 monitors, for instance). In this case, the entire display area is |
| * returned. |
| * |
| * Because the center point is arbitrarily settable by the user, it could |
| * fit neither of the cases above. The fallback case is to simply return |
| * the combined area for all screens. |
| */ |
| protected Rectangle getXineramaWindowBounds() { |
| Point center = getCenterPoint(); |
| Rectangle unionRect, tempRect; |
| GraphicsDevice[] gds = getScreenDevices(); |
| Rectangle centerMonitorRect = null; |
| int i; |
| |
| // if center point is at the center of all monitors |
| // return union of all bounds |
| // |
| // MM*MM MMM M |
| // M*M * |
| // MMM M |
| |
| // if center point is at center of a single monitor (but not of all |
| // monitors) |
| // return bounds of single monitor |
| // |
| // MMM MM |
| // MM* *M |
| |
| // else, center is in some strange spot (such as on the border between |
| // monitors), and we should just return the union of all monitors |
| // |
| // MM MMM |
| // MM MMM |
| |
| unionRect = getUsableBounds(gds[0]); |
| |
| for (i = 0; i < gds.length; i++) { |
| tempRect = getUsableBounds(gds[i]); |
| if (centerMonitorRect == null && |
| // add a pixel or two for fudge-factor |
| (tempRect.width / 2) + tempRect.x > center.x - 1 && |
| (tempRect.height / 2) + tempRect.y > center.y - 1 && |
| (tempRect.width / 2) + tempRect.x < center.x + 1 && |
| (tempRect.height / 2) + tempRect.y < center.y + 1) { |
| centerMonitorRect = tempRect; |
| } |
| unionRect = unionRect.union(tempRect); |
| } |
| |
| // first: check for center of all monitors (video wall) |
| // add a pixel or two for fudge-factor |
| if ((unionRect.width / 2) + unionRect.x > center.x - 1 && |
| (unionRect.height / 2) + unionRect.y > center.y - 1 && |
| (unionRect.width / 2) + unionRect.x < center.x + 1 && |
| (unionRect.height / 2) + unionRect.y < center.y + 1) { |
| |
| if (screenLog.isLoggable(PlatformLogger.FINER)) { |
| screenLog.finer("Video Wall: center point is at center of all displays."); |
| } |
| return unionRect; |
| } |
| |
| // next, check if at center of one monitor |
| if (centerMonitorRect != null) { |
| if (screenLog.isLoggable(PlatformLogger.FINER)) { |
| screenLog.finer("Center point at center of a particular " + |
| "monitor, but not of the entire virtual display."); |
| } |
| return centerMonitorRect; |
| } |
| |
| // otherwise, the center is at some weird spot: return unionRect |
| if (screenLog.isLoggable(PlatformLogger.FINER)) { |
| screenLog.finer("Center point is somewhere strange - return union of all bounds."); |
| } |
| return unionRect; |
| } |
| |
| /** |
| * From the DisplayChangedListener interface; devices do not need |
| * to react to this event. |
| */ |
| @Override |
| public void paletteChanged() { |
| } |
| } |