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