1 /*
2  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.awt;
27 
28 import java.awt.AWTError;
29 import java.awt.GraphicsDevice;
30 import java.net.InetAddress;
31 import java.net.NetworkInterface;
32 import java.net.SocketException;
33 import java.net.UnknownHostException;
34 import java.util.Enumeration;
35 
36 import sun.java2d.SunGraphicsEnvironment;
37 import sun.java2d.SurfaceManagerFactory;
38 import sun.java2d.UnixSurfaceManagerFactory;
39 import sun.java2d.xr.XRSurfaceData;
40 import sun.util.logging.PlatformLogger;
41 
42 /**
43  * This is an implementation of a GraphicsEnvironment object for the
44  * default local GraphicsEnvironment used by the Java Runtime Environment
45  * for X11 environments.
46  *
47  * @see GraphicsDevice
48  * @see java.awt.GraphicsConfiguration
49  */
50 public final class X11GraphicsEnvironment extends SunGraphicsEnvironment {
51 
52     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11GraphicsEnvironment");
53     private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.screen.X11GraphicsEnvironment");
54 
55     private static Boolean xinerState;
56 
57     static {
java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Object>() { public Object run() { System.loadLibrary(R); if (!isHeadless()) { boolean glxRequested = false; String prop = System.getProperty(R); if (prop != null) { if (prop.equals(R) || prop.equals(R)) { glxRequested = true; } else if (prop.equals(R) || prop.equals(R)) { glxRequested = true; glxVerbose = true; } } boolean xRenderRequested = true; boolean xRenderIgnoreLinuxVersion = false; String xProp = System.getProperty(R); if (xProp != null) { if (xProp.equals(R) || xProp.equals(R)) { xRenderRequested = false; } else if (xProp.equals(R) || xProp.equals(R)) { xRenderRequested = true; xRenderVerbose = true; } if(xProp.equalsIgnoreCase(R) || xProp.equalsIgnoreCase(R)) { xRenderIgnoreLinuxVersion = true; } } initDisplay(glxRequested); if (glxRequested) { glxAvailable = initGLX(); if (glxVerbose && !glxAvailable) { System.out.println( R + R); } } if (xRenderRequested) { xRenderAvailable = initXRender(xRenderVerbose, xRenderIgnoreLinuxVersion); if (xRenderVerbose && !xRenderAvailable) { System.out.println( R); } } if (xRenderAvailable) { XRSurfaceData.initXRSurfaceData(); } } return null; } })58         java.security.AccessController.doPrivileged(
59                           new java.security.PrivilegedAction<Object>() {
60             public Object run() {
61                 System.loadLibrary("awt");
62 
63                 /*
64                  * Note: The MToolkit object depends on the static initializer
65                  * of X11GraphicsEnvironment to initialize the connection to
66                  * the X11 server.
67                  */
68                 if (!isHeadless()) {
69                     // first check the OGL system property
70                     boolean glxRequested = false;
71                     String prop = System.getProperty("sun.java2d.opengl");
72                     if (prop != null) {
73                         if (prop.equals("true") || prop.equals("t")) {
74                             glxRequested = true;
75                         } else if (prop.equals("True") || prop.equals("T")) {
76                             glxRequested = true;
77                             glxVerbose = true;
78                         }
79                     }
80 
81                     // Now check for XRender system property
82                     boolean xRenderRequested = true;
83                     boolean xRenderIgnoreLinuxVersion = false;
84                     String xProp = System.getProperty("sun.java2d.xrender");
85                         if (xProp != null) {
86                         if (xProp.equals("false") || xProp.equals("f")) {
87                             xRenderRequested = false;
88                         } else if (xProp.equals("True") || xProp.equals("T")) {
89                             xRenderRequested = true;
90                             xRenderVerbose = true;
91                         }
92 
93                         if(xProp.equalsIgnoreCase("t") || xProp.equalsIgnoreCase("true")) {
94                             xRenderIgnoreLinuxVersion = true;
95                         }
96                     }
97 
98                     // initialize the X11 display connection
99                     initDisplay(glxRequested);
100 
101                     // only attempt to initialize GLX if it was requested
102                     if (glxRequested) {
103                         glxAvailable = initGLX();
104                         if (glxVerbose && !glxAvailable) {
105                             System.out.println(
106                                 "Could not enable OpenGL " +
107                                 "pipeline (GLX 1.3 not available)");
108                         }
109                     }
110 
111                     // only attempt to initialize Xrender if it was requested
112                     if (xRenderRequested) {
113                         xRenderAvailable = initXRender(xRenderVerbose, xRenderIgnoreLinuxVersion);
114                         if (xRenderVerbose && !xRenderAvailable) {
115                             System.out.println(
116                                          "Could not enable XRender pipeline");
117                         }
118                     }
119 
120                     if (xRenderAvailable) {
121                         XRSurfaceData.initXRSurfaceData();
122                     }
123                 }
124 
125                 return null;
126             }
127          });
128 
129         // Install the correct surface manager factory.
SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory())130         SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory());
131 
132     }
133 
134 
135     private static boolean glxAvailable;
136     private static boolean glxVerbose;
137 
initGLX()138     private static native boolean initGLX();
139 
isGLXAvailable()140     public static boolean isGLXAvailable() {
141         return glxAvailable;
142     }
143 
isGLXVerbose()144     public static boolean isGLXVerbose() {
145         return glxVerbose;
146     }
147 
148     private static boolean xRenderVerbose;
149     private static boolean xRenderAvailable;
150 
initXRender(boolean verbose, boolean ignoreLinuxVersion)151     private static native boolean initXRender(boolean verbose, boolean ignoreLinuxVersion);
isXRenderAvailable()152     public static boolean isXRenderAvailable() {
153         return xRenderAvailable;
154     }
155 
isXRenderVerbose()156     public static boolean isXRenderVerbose() {
157         return xRenderVerbose;
158     }
159 
160     /**
161      * Checks if Shared Memory extension can be used.
162      * Returns:
163      *   -1 if server doesn't support MITShm
164      *    1 if server supports it and it can be used
165      *    0 otherwise
166      */
checkShmExt()167     private static native int checkShmExt();
168 
getDisplayString()169     private static  native String getDisplayString();
170     private Boolean isDisplayLocal;
171 
172     /**
173      * This should only be called from the static initializer, so no need for
174      * the synchronized keyword.
175      */
initDisplay(boolean glxRequested)176     private static native void initDisplay(boolean glxRequested);
177 
X11GraphicsEnvironment()178     public X11GraphicsEnvironment() {
179     }
180 
getNumScreens()181     protected native int getNumScreens();
182 
makeScreenDevice(int screennum)183     protected GraphicsDevice makeScreenDevice(int screennum) {
184         return new X11GraphicsDevice(screennum);
185     }
186 
getDefaultScreenNum()187     private native int getDefaultScreenNum();
188     /**
189      * Returns the default screen graphics device.
190      */
getDefaultScreenDevice()191     public GraphicsDevice getDefaultScreenDevice() {
192         GraphicsDevice[] screens = getScreenDevices();
193         if (screens.length == 0) {
194             throw new AWTError("no screen devices");
195         }
196         int index = getDefaultScreenNum();
197         return screens[0 < index && index < screens.length ? index : 0];
198     }
199 
isDisplayLocal()200     public boolean isDisplayLocal() {
201         if (isDisplayLocal == null) {
202             SunToolkit.awtLock();
203             try {
204                 if (isDisplayLocal == null) {
205                     isDisplayLocal = Boolean.valueOf(_isDisplayLocal());
206                 }
207             } finally {
208                 SunToolkit.awtUnlock();
209             }
210         }
211         return isDisplayLocal.booleanValue();
212     }
213 
_isDisplayLocal()214     private static boolean _isDisplayLocal() {
215         if (isHeadless()) {
216             return true;
217         }
218 
219         String isRemote = java.security.AccessController.doPrivileged(
220             new sun.security.action.GetPropertyAction("sun.java2d.remote"));
221         if (isRemote != null) {
222             return isRemote.equals("false");
223         }
224 
225         int shm = checkShmExt();
226         if (shm != -1) {
227             return (shm == 1);
228         }
229 
230         // If XServer doesn't support ShMem extension,
231         // try the other way
232 
233         String display = getDisplayString();
234         int ind = display.indexOf(':');
235         final String hostName = display.substring(0, ind);
236         if (ind <= 0) {
237             // ':0' case
238             return true;
239         }
240 
241         Boolean result = java.security.AccessController.doPrivileged(
242             new java.security.PrivilegedAction<Boolean>() {
243             public Boolean run() {
244                 InetAddress[] remAddr = null;
245                 Enumeration<InetAddress> locals = null;
246                 Enumeration<NetworkInterface> interfaces = null;
247                 try {
248                     interfaces = NetworkInterface.getNetworkInterfaces();
249                     remAddr = InetAddress.getAllByName(hostName);
250                     if (remAddr == null) {
251                         return Boolean.FALSE;
252                     }
253                 } catch (UnknownHostException e) {
254                     System.err.println("Unknown host: " + hostName);
255                     return Boolean.FALSE;
256                 } catch (SocketException e1) {
257                     System.err.println(e1.getMessage());
258                     return Boolean.FALSE;
259                 }
260 
261                 for (; interfaces.hasMoreElements();) {
262                     locals = interfaces.nextElement().getInetAddresses();
263                     for (; locals.hasMoreElements();) {
264                         final InetAddress localAddr = locals.nextElement();
265                         for (int i = 0; i < remAddr.length; i++) {
266                             if (localAddr.equals(remAddr[i])) {
267                                 return Boolean.TRUE;
268                             }
269                         }
270                     }
271                 }
272                 return Boolean.FALSE;
273             }});
274         return result.booleanValue();
275     }
276 
277 
278 
279     /**
280      * Returns face name for default font, or null if
281      * no face names are used for CompositeFontDescriptors
282      * for this platform.
283      */
getDefaultFontFaceName()284     public String getDefaultFontFaceName() {
285 
286         return null;
287     }
288 
pRunningXinerama()289     private static native boolean pRunningXinerama();
290 
runningXinerama()291     public boolean runningXinerama() {
292         if (xinerState == null) {
293             // pRunningXinerama() simply returns a global boolean variable,
294             // so there is no need to synchronize here
295             xinerState = Boolean.valueOf(pRunningXinerama());
296             if (screenLog.isLoggable(PlatformLogger.Level.FINER)) {
297                 screenLog.finer("Running Xinerama: " + xinerState);
298             }
299         }
300         return xinerState.booleanValue();
301     }
302 
303     /**
304      * From the DisplayChangedListener interface; devices do not need
305      * to react to this event.
306      */
307     @Override
paletteChanged()308     public void paletteChanged() {
309     }
310 }
311