1 /* 2 * Copyright (c) 1997, 2015, 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.awt.Point; 31 import java.awt.Rectangle; 32 import java.net.InetAddress; 33 import java.net.NetworkInterface; 34 import java.net.SocketException; 35 import java.net.UnknownHostException; 36 37 import java.util.*; 38 39 import sun.java2d.SunGraphicsEnvironment; 40 import sun.java2d.SurfaceManagerFactory; 41 import sun.java2d.UnixSurfaceManagerFactory; 42 import sun.util.logging.PlatformLogger; 43 import sun.java2d.xr.XRSurfaceData; 44 45 /** 46 * This is an implementation of a GraphicsEnvironment object for the 47 * default local GraphicsEnvironment used by the Java Runtime Environment 48 * for X11 environments. 49 * 50 * @see GraphicsDevice 51 * @see java.awt.GraphicsConfiguration 52 */ 53 public final class X11GraphicsEnvironment extends SunGraphicsEnvironment { 54 55 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11GraphicsEnvironment"); 56 private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.screen.X11GraphicsEnvironment"); 57 58 private static Boolean xinerState; 59 60 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; } })61 java.security.AccessController.doPrivileged( 62 new java.security.PrivilegedAction<Object>() { 63 public Object run() { 64 System.loadLibrary("awt"); 65 66 /* 67 * Note: The MToolkit object depends on the static initializer 68 * of X11GraphicsEnvironment to initialize the connection to 69 * the X11 server. 70 */ 71 if (!isHeadless()) { 72 // first check the OGL system property 73 boolean glxRequested = false; 74 String prop = System.getProperty("sun.java2d.opengl"); 75 if (prop != null) { 76 if (prop.equals("true") || prop.equals("t")) { 77 glxRequested = true; 78 } else if (prop.equals("True") || prop.equals("T")) { 79 glxRequested = true; 80 glxVerbose = true; 81 } 82 } 83 84 // Now check for XRender system property 85 boolean xRenderRequested = true; 86 boolean xRenderIgnoreLinuxVersion = false; 87 String xProp = System.getProperty("sun.java2d.xrender"); 88 if (xProp != null) { 89 if (xProp.equals("false") || xProp.equals("f")) { 90 xRenderRequested = false; 91 } else if (xProp.equals("True") || xProp.equals("T")) { 92 xRenderRequested = true; 93 xRenderVerbose = true; 94 } 95 96 if(xProp.equalsIgnoreCase("t") || xProp.equalsIgnoreCase("true")) { 97 xRenderIgnoreLinuxVersion = true; 98 } 99 } 100 101 // initialize the X11 display connection 102 initDisplay(glxRequested); 103 104 // only attempt to initialize GLX if it was requested 105 if (glxRequested) { 106 glxAvailable = initGLX(); 107 if (glxVerbose && !glxAvailable) { 108 System.out.println( 109 "Could not enable OpenGL " + 110 "pipeline (GLX 1.3 not available)"); 111 } 112 } 113 114 // only attempt to initialize Xrender if it was requested 115 if (xRenderRequested) { 116 xRenderAvailable = initXRender(xRenderVerbose, xRenderIgnoreLinuxVersion); 117 if (xRenderVerbose && !xRenderAvailable) { 118 System.out.println( 119 "Could not enable XRender pipeline"); 120 } 121 } 122 123 if (xRenderAvailable) { 124 XRSurfaceData.initXRSurfaceData(); 125 } 126 } 127 128 return null; 129 } 130 }); 131 132 // Install the correct surface manager factory. SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory())133 SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory()); 134 135 } 136 137 138 private static boolean glxAvailable; 139 private static boolean glxVerbose; 140 initGLX()141 private static native boolean initGLX(); 142 isGLXAvailable()143 public static boolean isGLXAvailable() { 144 return glxAvailable; 145 } 146 isGLXVerbose()147 public static boolean isGLXVerbose() { 148 return glxVerbose; 149 } 150 151 private static boolean xRenderVerbose; 152 private static boolean xRenderAvailable; 153 initXRender(boolean verbose, boolean ignoreLinuxVersion)154 private static native boolean initXRender(boolean verbose, boolean ignoreLinuxVersion); isXRenderAvailable()155 public static boolean isXRenderAvailable() { 156 return xRenderAvailable; 157 } 158 isXRenderVerbose()159 public static boolean isXRenderVerbose() { 160 return xRenderVerbose; 161 } 162 163 /** 164 * Checks if Shared Memory extension can be used. 165 * Returns: 166 * -1 if server doesn't support MITShm 167 * 1 if server supports it and it can be used 168 * 0 otherwise 169 */ checkShmExt()170 private static native int checkShmExt(); 171 getDisplayString()172 private static native String getDisplayString(); 173 private Boolean isDisplayLocal; 174 175 /** 176 * This should only be called from the static initializer, so no need for 177 * the synchronized keyword. 178 */ initDisplay(boolean glxRequested)179 private static native void initDisplay(boolean glxRequested); 180 X11GraphicsEnvironment()181 public X11GraphicsEnvironment() { 182 } 183 getNumScreens()184 protected native int getNumScreens(); 185 makeScreenDevice(int screennum)186 protected GraphicsDevice makeScreenDevice(int screennum) { 187 return new X11GraphicsDevice(screennum); 188 } 189 getDefaultScreenNum()190 private native int getDefaultScreenNum(); 191 /** 192 * Returns the default screen graphics device. 193 */ getDefaultScreenDevice()194 public GraphicsDevice getDefaultScreenDevice() { 195 GraphicsDevice[] screens = getScreenDevices(); 196 if (screens.length == 0) { 197 throw new AWTError("no screen devices"); 198 } 199 int index = getDefaultScreenNum(); 200 return screens[0 < index && index < screens.length ? index : 0]; 201 } 202 isDisplayLocal()203 public boolean isDisplayLocal() { 204 if (isDisplayLocal == null) { 205 SunToolkit.awtLock(); 206 try { 207 if (isDisplayLocal == null) { 208 isDisplayLocal = Boolean.valueOf(_isDisplayLocal()); 209 } 210 } finally { 211 SunToolkit.awtUnlock(); 212 } 213 } 214 return isDisplayLocal.booleanValue(); 215 } 216 _isDisplayLocal()217 private static boolean _isDisplayLocal() { 218 if (isHeadless()) { 219 return true; 220 } 221 222 String isRemote = java.security.AccessController.doPrivileged( 223 new sun.security.action.GetPropertyAction("sun.java2d.remote")); 224 if (isRemote != null) { 225 return isRemote.equals("false"); 226 } 227 228 int shm = checkShmExt(); 229 if (shm != -1) { 230 return (shm == 1); 231 } 232 233 // If XServer doesn't support ShMem extension, 234 // try the other way 235 236 String display = getDisplayString(); 237 int ind = display.indexOf(':'); 238 final String hostName = display.substring(0, ind); 239 if (ind <= 0) { 240 // ':0' case 241 return true; 242 } 243 244 Boolean result = java.security.AccessController.doPrivileged( 245 new java.security.PrivilegedAction<Boolean>() { 246 public Boolean run() { 247 InetAddress remAddr[] = null; 248 Enumeration<InetAddress> locals = null; 249 Enumeration<NetworkInterface> interfaces = null; 250 try { 251 interfaces = NetworkInterface.getNetworkInterfaces(); 252 remAddr = InetAddress.getAllByName(hostName); 253 if (remAddr == null) { 254 return Boolean.FALSE; 255 } 256 } catch (UnknownHostException e) { 257 System.err.println("Unknown host: " + hostName); 258 return Boolean.FALSE; 259 } catch (SocketException e1) { 260 System.err.println(e1.getMessage()); 261 return Boolean.FALSE; 262 } 263 264 for (; interfaces.hasMoreElements();) { 265 locals = interfaces.nextElement().getInetAddresses(); 266 for (; locals.hasMoreElements();) { 267 final InetAddress localAddr = locals.nextElement(); 268 for (int i = 0; i < remAddr.length; i++) { 269 if (localAddr.equals(remAddr[i])) { 270 return Boolean.TRUE; 271 } 272 } 273 } 274 } 275 return Boolean.FALSE; 276 }}); 277 return result.booleanValue(); 278 } 279 280 281 282 /** 283 * Returns face name for default font, or null if 284 * no face names are used for CompositeFontDescriptors 285 * for this platform. 286 */ getDefaultFontFaceName()287 public String getDefaultFontFaceName() { 288 289 return null; 290 } 291 pRunningXinerama()292 private static native boolean pRunningXinerama(); getXineramaCenterPoint()293 private static native Point getXineramaCenterPoint(); 294 295 /** 296 * Override for Xinerama case: call new Solaris API for getting the correct 297 * centering point from the windowing system. 298 */ getCenterPoint()299 public Point getCenterPoint() { 300 if (runningXinerama()) { 301 Point p = getXineramaCenterPoint(); 302 if (p != null) { 303 return p; 304 } 305 } 306 return super.getCenterPoint(); 307 } 308 309 /** 310 * Override for Xinerama case 311 */ getMaximumWindowBounds()312 public Rectangle getMaximumWindowBounds() { 313 if (runningXinerama()) { 314 return getXineramaWindowBounds(); 315 } else { 316 return super.getMaximumWindowBounds(); 317 } 318 } 319 runningXinerama()320 public boolean runningXinerama() { 321 if (xinerState == null) { 322 // pRunningXinerama() simply returns a global boolean variable, 323 // so there is no need to synchronize here 324 xinerState = Boolean.valueOf(pRunningXinerama()); 325 if (screenLog.isLoggable(PlatformLogger.Level.FINER)) { 326 screenLog.finer("Running Xinerama: " + xinerState); 327 } 328 } 329 return xinerState.booleanValue(); 330 } 331 332 /** 333 * Return the bounds for a centered Window on a system running in Xinerama 334 * mode. 335 * 336 * Calculations are based on the assumption of a perfectly rectangular 337 * display area (display edges line up with one another, and displays 338 * have consistent width and/or height). 339 * 340 * The bounds to return depend on the arrangement of displays and on where 341 * Windows are to be centered. There are two common situations: 342 * 343 * 1) The center point lies at the center of the combined area of all the 344 * displays. In this case, the combined area of all displays is 345 * returned. 346 * 347 * 2) The center point lies at the center of a single display. In this case 348 * the user most likely wants centered Windows to be constrained to that 349 * single display. The boundaries of the one display are returned. 350 * 351 * It is possible for the center point to be at both the center of the 352 * entire display space AND at the center of a single monitor (a square of 353 * 9 monitors, for instance). In this case, the entire display area is 354 * returned. 355 * 356 * Because the center point is arbitrarily settable by the user, it could 357 * fit neither of the cases above. The fallback case is to simply return 358 * the combined area for all screens. 359 */ getXineramaWindowBounds()360 protected Rectangle getXineramaWindowBounds() { 361 Point center = getCenterPoint(); 362 Rectangle unionRect, tempRect; 363 GraphicsDevice[] gds = getScreenDevices(); 364 Rectangle centerMonitorRect = null; 365 int i; 366 367 // if center point is at the center of all monitors 368 // return union of all bounds 369 // 370 // MM*MM MMM M 371 // M*M * 372 // MMM M 373 374 // if center point is at center of a single monitor (but not of all 375 // monitors) 376 // return bounds of single monitor 377 // 378 // MMM MM 379 // MM* *M 380 381 // else, center is in some strange spot (such as on the border between 382 // monitors), and we should just return the union of all monitors 383 // 384 // MM MMM 385 // MM MMM 386 387 unionRect = getUsableBounds(gds[0]); 388 389 for (i = 0; i < gds.length; i++) { 390 tempRect = getUsableBounds(gds[i]); 391 if (centerMonitorRect == null && 392 // add a pixel or two for fudge-factor 393 (tempRect.width / 2) + tempRect.x > center.x - 1 && 394 (tempRect.height / 2) + tempRect.y > center.y - 1 && 395 (tempRect.width / 2) + tempRect.x < center.x + 1 && 396 (tempRect.height / 2) + tempRect.y < center.y + 1) { 397 centerMonitorRect = tempRect; 398 } 399 unionRect = unionRect.union(tempRect); 400 } 401 402 // first: check for center of all monitors (video wall) 403 // add a pixel or two for fudge-factor 404 if ((unionRect.width / 2) + unionRect.x > center.x - 1 && 405 (unionRect.height / 2) + unionRect.y > center.y - 1 && 406 (unionRect.width / 2) + unionRect.x < center.x + 1 && 407 (unionRect.height / 2) + unionRect.y < center.y + 1) { 408 409 if (screenLog.isLoggable(PlatformLogger.Level.FINER)) { 410 screenLog.finer("Video Wall: center point is at center of all displays."); 411 } 412 return unionRect; 413 } 414 415 // next, check if at center of one monitor 416 if (centerMonitorRect != null) { 417 if (screenLog.isLoggable(PlatformLogger.Level.FINER)) { 418 screenLog.finer("Center point at center of a particular " + 419 "monitor, but not of the entire virtual display."); 420 } 421 return centerMonitorRect; 422 } 423 424 // otherwise, the center is at some weird spot: return unionRect 425 if (screenLog.isLoggable(PlatformLogger.Level.FINER)) { 426 screenLog.finer("Center point is somewhere strange - return union of all bounds."); 427 } 428 return unionRect; 429 } 430 431 /** 432 * From the DisplayChangedListener interface; devices do not need 433 * to react to this event. 434 */ 435 @Override paletteChanged()436 public void paletteChanged() { 437 } 438 } 439