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