|
1 | 1 | /*
|
2 |
| - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * This code is free software; you can redistribute it and/or modify it
|
|
27 | 27 |
|
28 | 28 | import java.awt.AWTError;
|
29 | 29 | import java.awt.GraphicsDevice;
|
| 30 | +import java.lang.ref.WeakReference; |
30 | 31 | import java.net.InetAddress;
|
31 | 32 | import java.net.NetworkInterface;
|
32 | 33 | import java.net.SocketException;
|
33 | 34 | import java.net.UnknownHostException;
|
| 35 | +import java.util.ArrayList; |
34 | 36 | import java.util.Enumeration;
|
| 37 | +import java.util.HashMap; |
| 38 | +import java.util.List; |
| 39 | +import java.util.ListIterator; |
| 40 | +import java.util.Map; |
35 | 41 |
|
| 42 | +import sun.awt.X11.XToolkit; |
36 | 43 | import sun.java2d.SunGraphicsEnvironment;
|
37 | 44 | import sun.java2d.SurfaceManagerFactory;
|
38 | 45 | import sun.java2d.UnixSurfaceManagerFactory;
|
39 | 46 | import sun.java2d.xr.XRSurfaceData;
|
40 |
| -import sun.util.logging.PlatformLogger; |
41 | 47 |
|
42 | 48 | /**
|
43 | 49 | * This is an implementation of a GraphicsEnvironment object for the
|
|
49 | 55 | */
|
50 | 56 | public final class X11GraphicsEnvironment extends SunGraphicsEnvironment {
|
51 | 57 |
|
52 |
| - private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11GraphicsEnvironment"); |
53 |
| - private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.screen.X11GraphicsEnvironment"); |
54 |
| - |
55 |
| - private static Boolean xinerState; |
56 |
| - |
57 | 58 | static {
|
58 | 59 | java.security.AccessController.doPrivileged(
|
59 | 60 | new java.security.PrivilegedAction<Object>() {
|
@@ -169,32 +170,109 @@ public static boolean isXRenderVerbose() {
|
169 | 170 | private static native String getDisplayString();
|
170 | 171 | private Boolean isDisplayLocal;
|
171 | 172 |
|
| 173 | + /** Available X11 screens. */ |
| 174 | + private final Map<Integer, X11GraphicsDevice> devices = new HashMap<>(5); |
| 175 | + |
| 176 | + /** |
| 177 | + * The key in the {@link #devices} for the main screen. |
| 178 | + */ |
| 179 | + private int mainScreen; |
| 180 | + |
| 181 | + // list of invalidated graphics devices (those which were removed) |
| 182 | + private List<WeakReference<X11GraphicsDevice>> oldDevices = new ArrayList<>(); |
| 183 | + |
172 | 184 | /**
|
173 | 185 | * This should only be called from the static initializer, so no need for
|
174 | 186 | * the synchronized keyword.
|
175 | 187 | */
|
176 | 188 | private static native void initDisplay(boolean glxRequested);
|
177 | 189 |
|
| 190 | + protected native int getNumScreens(); |
| 191 | + |
| 192 | + private native int getDefaultScreenNum(); |
| 193 | + |
178 | 194 | public X11GraphicsEnvironment() {
|
| 195 | + if (isHeadless()) { |
| 196 | + return; |
| 197 | + } |
| 198 | + |
| 199 | + /* Populate the device table */ |
| 200 | + rebuildDevices(); |
179 | 201 | }
|
180 | 202 |
|
181 |
| - protected native int getNumScreens(); |
| 203 | + /** |
| 204 | + * Initialize the native list of devices. |
| 205 | + */ |
| 206 | + private static native void initNativeData(); |
182 | 207 |
|
183 |
| - protected GraphicsDevice makeScreenDevice(int screennum) { |
184 |
| - return new X11GraphicsDevice(screennum); |
| 208 | + /** |
| 209 | + * Updates the list of devices and notify listeners. |
| 210 | + */ |
| 211 | + public void rebuildDevices() { |
| 212 | + XToolkit.awtLock(); |
| 213 | + try { |
| 214 | + initNativeData(); |
| 215 | + initDevices(); |
| 216 | + } finally { |
| 217 | + XToolkit.awtUnlock(); |
| 218 | + } |
| 219 | + displayChanged(); |
185 | 220 | }
|
186 | 221 |
|
187 |
| - private native int getDefaultScreenNum(); |
188 | 222 | /**
|
189 |
| - * Returns the default screen graphics device. |
| 223 | + * (Re)create all X11GraphicsDevices, reuses a devices if it is possible. |
190 | 224 | */
|
191 |
| - public GraphicsDevice getDefaultScreenDevice() { |
192 |
| - GraphicsDevice[] screens = getScreenDevices(); |
193 |
| - if (screens.length == 0) { |
| 225 | + private synchronized void initDevices() { |
| 226 | + Map<Integer, X11GraphicsDevice> old = new HashMap<>(devices); |
| 227 | + devices.clear(); |
| 228 | + |
| 229 | + int numScreens = getNumScreens(); |
| 230 | + if (numScreens == 0) { |
194 | 231 | throw new AWTError("no screen devices");
|
195 | 232 | }
|
196 | 233 | int index = getDefaultScreenNum();
|
197 |
| - return screens[0 < index && index < screens.length ? index : 0]; |
| 234 | + mainScreen = 0 < index && index < screens.length ? index : 0; |
| 235 | + |
| 236 | + for (int id = 0; id < numScreens; ++id) { |
| 237 | + devices.put(id, old.containsKey(id) ? old.remove(id) : |
| 238 | + new X11GraphicsDevice(id)); |
| 239 | + } |
| 240 | + // if a device was not reused it should be invalidated |
| 241 | + for (X11GraphicsDevice gd : old.values()) { |
| 242 | + oldDevices.add(new WeakReference<>(gd)); |
| 243 | + } |
| 244 | + // Need to notify old devices, in case the user hold the reference to it |
| 245 | + for (ListIterator<WeakReference<X11GraphicsDevice>> it = |
| 246 | + oldDevices.listIterator(); it.hasNext(); ) { |
| 247 | + X11GraphicsDevice gd = it.next().get(); |
| 248 | + if (gd != null) { |
| 249 | + gd.invalidate(devices.get(mainScreen)); |
| 250 | + gd.displayChanged(); |
| 251 | + } else { |
| 252 | + // no more references to this device, remove it |
| 253 | + it.remove(); |
| 254 | + } |
| 255 | + } |
| 256 | + } |
| 257 | + |
| 258 | + @Override |
| 259 | + public synchronized GraphicsDevice getDefaultScreenDevice() { |
| 260 | + return devices.get(mainScreen); |
| 261 | + } |
| 262 | + |
| 263 | + @Override |
| 264 | + public synchronized GraphicsDevice[] getScreenDevices() { |
| 265 | + return devices.values().toArray(new X11GraphicsDevice[0]); |
| 266 | + } |
| 267 | + |
| 268 | + public synchronized GraphicsDevice getScreenDevice(int screen) { |
| 269 | + return devices.get(screen); |
| 270 | + } |
| 271 | + |
| 272 | + @Override |
| 273 | + protected GraphicsDevice makeScreenDevice(int screennum) { |
| 274 | + throw new UnsupportedOperationException("This method is unused and" + |
| 275 | + "should not be called in this implementation"); |
198 | 276 | }
|
199 | 277 |
|
200 | 278 | public boolean isDisplayLocal() {
|
@@ -289,15 +367,7 @@ public String getDefaultFontFaceName() {
|
289 | 367 | private static native boolean pRunningXinerama();
|
290 | 368 |
|
291 | 369 | public boolean runningXinerama() {
|
292 |
| - if (xinerState == null) { |
293 |
| - // pRunningXinerama() simply returns a global boolean variable, |
294 |
| - // so there is no need to synchronize here |
295 |
| - xinerState = Boolean.valueOf(pRunningXinerama()); |
296 |
| - if (screenLog.isLoggable(PlatformLogger.Level.FINER)) { |
297 |
| - screenLog.finer("Running Xinerama: " + xinerState); |
298 |
| - } |
299 |
| - } |
300 |
| - return xinerState.booleanValue(); |
| 370 | + return pRunningXinerama(); |
301 | 371 | }
|
302 | 372 |
|
303 | 373 | /**
|
|
0 commit comments