1 /*
2 * Copyright (c) 1997, 2015, 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 // Reset the static GC for the (possibly new) default screen
207 WToolkit.resetGC();
208
209 // notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and
210 // CachingSurfaceManagers) about the display change event
211 displayChanger.notifyListeners();
212 // note: do not call super.displayChanged, we've already done everything
213 }
214
215
216 /*
217 * ----END DISPLAY CHANGE SUPPORT----
218 */
219
220 protected GraphicsDevice makeScreenDevice(int screennum) {
221 GraphicsDevice device = null;
222 if (WindowsFlags.isD3DEnabled()) {
223 device = D3DGraphicsDevice.createDevice(screennum);
224 }
225 if (device == null) {
226 device = new Win32GraphicsDevice(screennum);
227 }
228 return device;
229 }
230
231 public boolean isDisplayLocal() {
232 return true;
233 }
234
235 @Override
236 public boolean isFlipStrategyPreferred(ComponentPeer peer) {
237 GraphicsConfiguration gc;
238 if (peer != null && (gc = peer.getGraphicsConfiguration()) != null) {
239 GraphicsDevice gd = gc.getDevice();
240 if (gd instanceof D3DGraphicsDevice) {
241 return ((D3DGraphicsDevice)gd).isD3DEnabledOnDevice();
242 }
243 }
244 return false;
245 }
246
247 private static volatile boolean isDWMCompositionEnabled;
248 /**
249 * Returns true if dwm composition is currently enabled, false otherwise.
250 *
251 * @return true if dwm composition is enabled, false otherwise
252 */
253 public static boolean isDWMCompositionEnabled() {
254 return isDWMCompositionEnabled;
255 }
256
257 /**
258 * Called from the native code when DWM composition state changed.
259 * May be called multiple times during the lifetime of the application.
260 * REMIND: we may want to create a listener mechanism for this.
261 *
262 * Note: called on the Toolkit thread, no user code or locks are allowed.
263 *
264 * @param enabled indicates the state of dwm composition
265 */
266 private static void dwmCompositionChanged(boolean enabled) {
267 isDWMCompositionEnabled = enabled;
268 }
269
270 /**
271 * Used to find out if the OS is Windows Vista or later.
272 *
273 * @return {@code true} if the OS is Vista or later, {@code false} otherwise
274 */
275 public static native boolean isVistaOS();
276 }