1 /* 2 * Copyright (c) 2011, 2013, 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.*; 29 import java.util.*; 30 31 import sun.java2d.*; 32 33 /** 34 * This is an implementation of a GraphicsEnvironment object for the default 35 * local GraphicsEnvironment used by the Java Runtime Environment for Mac OS X 36 * GUI environments. 37 * 38 * @see GraphicsDevice 39 * @see GraphicsConfiguration 40 */ 41 public final class CGraphicsEnvironment extends SunGraphicsEnvironment { 42 43 // Global initialization of the Cocoa runtime. 44 private static native void initCocoa(); 45 46 /** 47 * Fetch an array of all valid CoreGraphics display identifiers. 48 */ 49 private static native int[] getDisplayIDs(); 50 51 /** 52 * Fetch the CoreGraphics display ID for the 'main' display. 53 */ 54 private static native int getMainDisplayID(); 55 56 /** 57 * Noop function that just acts as an entry point for someone to force a 58 * static initialization of this class. 59 */ 60 public static void init() { } 61 62 static { 63 java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() { 64 public Void run() { 65 System.loadLibrary("awt"); 66 return null; 67 } 68 }); 69 70 java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() { 71 public Void run() { 72 if (isHeadless()) return null; 73 initCocoa(); 74 return null; 75 } 76 }); 77 78 // Install the correct surface manager factory. 79 SurfaceManagerFactory.setInstance(new MacosxSurfaceManagerFactory()); 80 } 81 82 /** 83 * Register the instance with CGDisplayRegisterReconfigurationCallback(). 84 * The registration uses a weak global reference -- if our instance is 85 * garbage collected, the reference will be dropped. 86 * 87 * @return Return the registration context (a pointer). 88 */ 89 private native long registerDisplayReconfiguration(); 90 91 /** 92 * Remove the instance's registration with CGDisplayRemoveReconfigurationCallback() 93 */ 94 private native void deregisterDisplayReconfiguration(long context); 95 96 /** Available CoreGraphics displays. */ 97 private final Map<Integer, CGraphicsDevice> devices = new HashMap<>(5); 98 99 /** Reference to the display reconfiguration callback context. */ 100 private final long displayReconfigContext; 101 102 /** 103 * Construct a new instance. 104 */ 105 public CGraphicsEnvironment() { 106 if (isHeadless()) { 107 displayReconfigContext = 0L; 108 return; 109 } 110 111 /* Populate the device table */ 112 initDevices(); 113 114 /* Register our display reconfiguration listener */ 115 displayReconfigContext = registerDisplayReconfiguration(); 116 if (displayReconfigContext == 0L) { 117 throw new RuntimeException("Could not register CoreGraphics display reconfiguration callback"); 118 } 119 } 120 121 /** 122 * Called by the CoreGraphics Display Reconfiguration Callback. 123 * 124 * @param displayId CoreGraphics displayId 125 * @param removed true if displayId was removed, false otherwise. 126 */ 127 void _displayReconfiguration(final int displayId, final boolean removed) { 128 synchronized (this) { 129 if (removed && devices.containsKey(displayId)) { 130 final CGraphicsDevice gd = devices.remove(displayId); 131 gd.invalidate(getMainDisplayID()); 132 gd.displayChanged(); 133 } 134 } 135 initDevices(); 136 } 137 138 @Override 139 protected void finalize() throws Throwable { 140 try { 141 super.finalize(); 142 } finally { 143 deregisterDisplayReconfiguration(displayReconfigContext); 144 } 145 } 146 147 /** 148 * (Re)create all CGraphicsDevices, reuses a devices if it is possible. 149 */ 150 private void initDevices() { 151 synchronized (this) { 152 final Map<Integer, CGraphicsDevice> old = new HashMap<>(devices); 153 devices.clear(); 154 155 int mainID = getMainDisplayID(); 156 157 // initialization of the graphics device may change 158 // list of displays on hybrid systems via an activation 159 // of discrete video. 160 // So, we initialize the main display first, and then 161 // retrieve actual list of displays. 162 if (!old.containsKey(mainID)) { 163 old.put(mainID, new CGraphicsDevice(mainID)); 164 } 165 166 for (final int id : getDisplayIDs()) { 167 devices.put(id, old.containsKey(id) ? old.get(id) 168 : new CGraphicsDevice(id)); 169 } 170 } 171 displayChanged(); 172 } 173 174 @Override 175 public synchronized GraphicsDevice getDefaultScreenDevice() throws HeadlessException { 176 final int mainDisplayID = getMainDisplayID(); 177 CGraphicsDevice d = devices.get(mainDisplayID); 178 if (d == null) { 179 // we do not expect that this may happen, the only response 180 // is to re-initialize the list of devices 181 initDevices(); 182 183 d = devices.get(mainDisplayID); 184 } 185 return d; 186 } 187 188 @Override 189 public synchronized GraphicsDevice[] getScreenDevices() throws HeadlessException { 190 return devices.values().toArray(new CGraphicsDevice[devices.values().size()]); 191 } 192 193 public synchronized GraphicsDevice getScreenDevice(int displayID) { 194 return devices.get(displayID); 195 } 196 197 @Override 198 protected synchronized int getNumScreens() { 199 return devices.size(); 200 } 201 202 @Override 203 protected GraphicsDevice makeScreenDevice(int screennum) { 204 throw new UnsupportedOperationException("This method is unused and should not be called in this implementation"); 205 } 206 207 @Override 208 public boolean isDisplayLocal() { 209 return true; 210 } 211 212 static String[] sLogicalFonts = { "Serif", "SansSerif", "Monospaced", "Dialog", "DialogInput" }; 213 214 @Override 215 public Font[] getAllFonts() { 216 217 Font[] newFonts; 218 Font[] superFonts = super.getAllFonts(); 219 220 int numLogical = sLogicalFonts.length; 221 int numOtherFonts = superFonts.length; 222 223 newFonts = new Font[numOtherFonts + numLogical]; 224 System.arraycopy(superFonts,0,newFonts,numLogical,numOtherFonts); 225 226 for (int i = 0; i < numLogical; i++) 227 { 228 newFonts[i] = new Font(sLogicalFonts[i], Font.PLAIN, 1); 229 } 230 return newFonts; 231 } 232 233 }