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