1 /* 2 * Copyright 1997-2009 Sun Microsystems, Inc. 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. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 package sun.awt; 27 28 import java.awt.GraphicsConfiguration; 29 import java.awt.GraphicsDevice; 30 import java.awt.GraphicsEnvironment; 31 import java.awt.Toolkit; 32 import java.awt.peer.ComponentPeer; 33 import java.io.File; 34 import java.io.IOException; 35 import java.lang.ref.WeakReference; 36 import java.util.ArrayList; 37 import java.util.ListIterator; 38 import java.util.NoSuchElementException; 39 import java.util.StringTokenizer; 40 import sun.awt.DisplayChangedListener; 41 import sun.awt.SunDisplayChanger; 42 import sun.awt.windows.WFontConfiguration; 43 import sun.awt.windows.WPrinterJob; 44 import sun.awt.windows.WToolkit; 45 import sun.font.FontManager; 46 import sun.font.FontManagerFactory; 47 import sun.font.SunFontManager; 48 import sun.java2d.SunGraphicsEnvironment; 49 import sun.java2d.SurfaceManagerFactory; 50 import sun.java2d.WindowsSurfaceManagerFactory; 51 import sun.java2d.d3d.D3DGraphicsDevice; 52 import sun.java2d.windows.WindowsFlags; 53 54 /** 55 * This is an implementation of a GraphicsEnvironment object for the 56 * default local GraphicsEnvironment used by the Java Runtime Environment 57 * for Windows. 58 * 59 * @see GraphicsDevice 60 * @see GraphicsConfiguration 61 */ 62 63 public class Win32GraphicsEnvironment 64 extends SunGraphicsEnvironment 65 { 66 static { 67 // Ensure awt is loaded already. Also, this forces static init 68 // of WToolkit and Toolkit, which we depend upon 69 WToolkit.loadLibraries(); 70 // setup flags before initializing native layer 71 WindowsFlags.initFlags(); 72 initDisplayWrapper(); 73 74 // Install correct surface manager factory. 75 SurfaceManagerFactory.setInstance(new WindowsSurfaceManagerFactory()); 76 } 77 78 /** 79 * Noop function that just acts as an entry point for someone to force 80 * a static initialization of this class. 81 */ 82 public static void init() {} 83 84 /** 85 * Initializes native components of the graphics environment. This 86 * includes everything from the native GraphicsDevice elements to 87 * the DirectX rendering layer. 88 */ 89 private static native void initDisplay(); 90 91 private static boolean displayInitialized; // = false; 92 public static void initDisplayWrapper() { 93 if (!displayInitialized) { 94 displayInitialized = true; 95 initDisplay(); 96 } 97 } 98 99 public Win32GraphicsEnvironment() { 100 } 101 102 protected native int getNumScreens(); 103 protected native int getDefaultScreen(); 104 105 public GraphicsDevice getDefaultScreenDevice() { 106 return getScreenDevices()[getDefaultScreen()]; 107 } 108 109 /** 110 * Returns the number of pixels per logical inch along the screen width. 111 * In a system with multiple display monitors, this value is the same for 112 * all monitors. 113 * @returns number of pixels per logical inch in X direction 114 */ 115 public native int getXResolution(); 116 /** 117 * Returns the number of pixels per logical inch along the screen height. 118 * In a system with multiple display monitors, this value is the same for 119 * all monitors. 120 * @returns number of pixels per logical inch in Y direction 121 */ 122 public native int getYResolution(); 123 124 125 /* 126 * ----DISPLAY CHANGE SUPPORT---- 127 */ 128 129 // list of invalidated graphics devices (those which were removed) 130 private ArrayList<WeakReference<Win32GraphicsDevice>> oldDevices; 131 /* 132 * From DisplayChangeListener interface. 133 * Called from WToolkit and executed on the event thread when the 134 * display settings are changed. 135 */ 136 @Override 137 public void displayChanged() { 138 // getNumScreens() will return the correct current number of screens 139 GraphicsDevice newDevices[] = new GraphicsDevice[getNumScreens()]; 140 GraphicsDevice oldScreens[] = screens; 141 // go through the list of current devices and determine if they 142 // could be reused, or will have to be replaced 143 if (oldScreens != null) { 144 for (int i = 0; i < oldScreens.length; i++) { 145 if (!(screens[i] instanceof Win32GraphicsDevice)) { 146 // REMIND: can we ever have anything other than Win32GD? 147 assert (false) : oldScreens[i]; 148 continue; 149 } 150 Win32GraphicsDevice gd = (Win32GraphicsDevice)oldScreens[i]; 151 // devices may be invalidated from the native code when the 152 // display change happens (device add/removal also causes a 153 // display change) 154 if (!gd.isValid()) { 155 if (oldDevices == null) { 156 oldDevices = 157 new ArrayList<WeakReference<Win32GraphicsDevice>>(); 158 } 159 oldDevices.add(new WeakReference<Win32GraphicsDevice>(gd)); 160 } else if (i < newDevices.length) { 161 // reuse the device 162 newDevices[i] = gd; 163 } 164 } 165 oldScreens = null; 166 } 167 // create the new devices (those that weren't reused) 168 for (int i = 0; i < newDevices.length; i++) { 169 if (newDevices[i] == null) { 170 newDevices[i] = makeScreenDevice(i); 171 } 172 } 173 // install the new array of devices 174 // Note: no synchronization here, it doesn't matter if a thread gets 175 // a new or an old array this time around 176 screens = newDevices; 177 for (GraphicsDevice gd : screens) { 178 if (gd instanceof DisplayChangedListener) { 179 ((DisplayChangedListener)gd).displayChanged(); 180 } 181 } 182 // re-invalidate all old devices. It's needed because those in the list 183 // may become "invalid" again - if the current default device is removed, 184 // for example. Also, they need to be notified about display 185 // changes as well. 186 if (oldDevices != null) { 187 int defScreen = getDefaultScreen(); 188 for (ListIterator<WeakReference<Win32GraphicsDevice>> it = 189 oldDevices.listIterator(); it.hasNext();) 190 { 191 Win32GraphicsDevice gd = it.next().get(); 192 if (gd != null) { 193 gd.invalidate(defScreen); 194 gd.displayChanged(); 195 } else { 196 // no more references to this device, remove it 197 it.remove(); 198 } 199 } 200 } 201 // Reset the static GC for the (possibly new) default screen 202 WToolkit.resetGC(); 203 204 // notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and 205 // CachingSurfaceManagers) about the display change event 206 displayChanger.notifyListeners(); 207 // note: do not call super.displayChanged, we've already done everything 208 } 209 210 211 /* 212 * ----END DISPLAY CHANGE SUPPORT---- 213 */ 214 215 /** 216 * Whether registerFontFile expects absolute or relative 217 * font file names. 218 */ 219 protected boolean useAbsoluteFontFileNames() { 220 return false; 221 } 222 223 protected GraphicsDevice makeScreenDevice(int screennum) { 224 GraphicsDevice device = null; 225 if (WindowsFlags.isD3DEnabled()) { 226 device = D3DGraphicsDevice.createDevice(screennum); 227 } 228 if (device == null) { 229 device = new Win32GraphicsDevice(screennum); 230 } 231 return device; 232 } 233 234 // Implements SunGraphicsEnvironment.createFontConfiguration. 235 protected FontConfiguration createFontConfiguration() { 236 FontConfiguration fc = new WFontConfiguration(SunFontManager.getInstance()); 237 fc.init(); 238 return fc; 239 } 240 241 public FontConfiguration createFontConfiguration(boolean preferLocaleFonts, 242 boolean preferPropFonts) { 243 244 return new WFontConfiguration(SunFontManager.getInstance(), 245 preferLocaleFonts,preferPropFonts); 246 } 247 248 public boolean isDisplayLocal() { 249 return true; 250 } 251 252 @Override 253 public boolean isFlipStrategyPreferred(ComponentPeer peer) { 254 GraphicsConfiguration gc; 255 if (peer != null && (gc = peer.getGraphicsConfiguration()) != null) { 256 GraphicsDevice gd = gc.getDevice(); 257 if (gd instanceof D3DGraphicsDevice) { 258 return ((D3DGraphicsDevice)gd).isD3DEnabledOnDevice(); 259 } 260 } 261 return false; 262 } 263 264 private static volatile boolean isDWMCompositionEnabled; 265 /** 266 * Returns true if dwm composition is currently enabled, false otherwise. 267 * 268 * @return true if dwm composition is enabled, false otherwise 269 */ 270 public static boolean isDWMCompositionEnabled() { 271 return isDWMCompositionEnabled; 272 } 273 274 /** 275 * Called from the native code when DWM composition state changed. 276 * May be called multiple times during the lifetime of the application. 277 * REMIND: we may want to create a listener mechanism for this. 278 * 279 * Note: called on the Toolkit thread, no user code or locks are allowed. 280 * 281 * @param enabled indicates the state of dwm composition 282 */ 283 private static void dwmCompositionChanged(boolean enabled) { 284 isDWMCompositionEnabled = enabled; 285 } 286 287 /** 288 * Used to find out if the OS is Windows Vista or later. 289 * 290 * @return {@code true} if the OS is Vista or later, {@code false} otherwise 291 */ 292 public static native boolean isVistaOS(); 293 }