1 /* 2 * Copyright (c) 2011, 2017, 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 * The key in the {@link #devices} for the main display. 84 */ 85 private int mainDisplayID; 86 87 /** Reference to the display reconfiguration callback context. */ 88 private final long displayReconfigContext; 89 90 /** 91 * Construct a new instance. 92 */ 93 public CGraphicsEnvironment() { 94 if (isHeadless()) { 95 displayReconfigContext = 0L; 96 return; 97 } 98 99 /* Populate the device table */ 100 initDevices(); 101 102 /* Register our display reconfiguration listener */ 103 displayReconfigContext = registerDisplayReconfiguration(); 104 if (displayReconfigContext == 0L) { 105 throw new RuntimeException("Could not register CoreGraphics display reconfiguration callback"); 106 } 107 } 108 109 /** 110 * Called by the CoreGraphics Display Reconfiguration Callback. 111 * 112 * @param displayId CoreGraphics displayId 113 * @param removed true if displayId was removed, false otherwise. 114 */ 115 void _displayReconfiguration(final int displayId, final boolean removed) { 116 synchronized (this) { 117 if (removed && devices.containsKey(displayId)) { 118 final CGraphicsDevice gd = devices.remove(displayId); 119 gd.invalidate(getMainDisplayID()); 120 gd.displayChanged(); 121 } 122 } 123 initDevices(); 124 } 125 126 @Override 127 @SuppressWarnings("deprecation") 128 protected void finalize() throws Throwable { 129 try { 130 super.finalize(); 131 } finally { 132 deregisterDisplayReconfiguration(displayReconfigContext); 133 } 134 } 135 136 /** 137 * (Re)create all CGraphicsDevices, reuses a devices if it is possible. 138 */ 139 private void initDevices() { 140 synchronized (this) { 141 final Map<Integer, CGraphicsDevice> old = new HashMap<>(devices); 142 devices.clear(); 143 144 mainDisplayID = getMainDisplayID(); 145 146 // initialization of the graphics device may change 147 // list of displays on hybrid systems via an activation 148 // of discrete video. 149 // So, we initialize the main display first, and then 150 // retrieve actual list of displays. 151 if (!old.containsKey(mainDisplayID)) { 152 old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID)); 153 } 154 155 for (final int id : getDisplayIDs()) { 156 devices.put(id, old.containsKey(id) ? old.get(id) 157 : new CGraphicsDevice(id)); 158 } 159 } 160 displayChanged(); 161 } 162 163 @Override 164 public synchronized GraphicsDevice getDefaultScreenDevice() throws HeadlessException { 165 CGraphicsDevice d = devices.get(mainDisplayID); 166 if (d == null) { 167 // we do not expect that this may happen, the only response 168 // is to re-initialize the list of devices 169 initDevices(); 170 171 d = devices.get(mainDisplayID); 172 if (d == null) { 173 throw new AWTError("no screen devices"); 174 } 175 } 176 return d; 177 } 178 179 @Override 180 public synchronized GraphicsDevice[] getScreenDevices() throws HeadlessException { 181 return devices.values().toArray(new CGraphicsDevice[devices.values().size()]); 182 } 183 184 public synchronized GraphicsDevice getScreenDevice(int displayID) { 185 return devices.get(displayID); 186 } 187 188 @Override 189 protected synchronized int getNumScreens() { 190 return devices.size(); 191 } 192 193 @Override 194 protected GraphicsDevice makeScreenDevice(int screennum) { 195 throw new UnsupportedOperationException("This method is unused and should not be called in this implementation"); 196 } 197 198 @Override 199 public boolean isDisplayLocal() { 200 return true; 201 } 202 203 static String[] sLogicalFonts = { "Serif", "SansSerif", "Monospaced", "Dialog", "DialogInput" }; 204 205 @Override 206 public Font[] getAllFonts() { 207 208 Font[] newFonts; 209 Font[] superFonts = super.getAllFonts(); 210 211 int numLogical = sLogicalFonts.length; 212 int numOtherFonts = superFonts.length; 213 214 newFonts = new Font[numOtherFonts + numLogical]; 215 System.arraycopy(superFonts,0,newFonts,numLogical,numOtherFonts); 216 217 for (int i = 0; i < numLogical; i++) 218 { 219 newFonts[i] = new Font(sLogicalFonts[i], Font.PLAIN, 1); 220 } 221 return newFonts; 222 } 223 224 }