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