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