1
1
/*
2
- * Copyright (c) 2011, 2018 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2011, 2020 , 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
25
25
26
26
package sun .awt ;
27
27
28
- import java .awt .AWTError ;
29
28
import java .awt .Font ;
30
29
import java .awt .GraphicsConfiguration ;
31
30
import java .awt .GraphicsDevice ;
@@ -112,7 +111,7 @@ public CGraphicsEnvironment() {
112
111
}
113
112
114
113
/* Populate the device table */
115
- initDevices ();
114
+ rebuildDevices ();
116
115
117
116
/* Register our display reconfiguration listener */
118
117
displayReconfigContext = registerDisplayReconfiguration ();
@@ -121,33 +120,27 @@ public CGraphicsEnvironment() {
121
120
}
122
121
}
123
122
123
+ /**
124
+ * Updates the list of devices and notify listeners.
125
+ */
126
+ private void rebuildDevices () {
127
+ initDevices ();
128
+ displayChanged ();
129
+ }
130
+
124
131
/**
125
132
* Called by the CoreGraphics Display Reconfiguration Callback.
126
133
*
127
134
* @param displayId CoreGraphics displayId
128
135
* @param removed true if displayId was removed, false otherwise.
129
136
*/
130
- void _displayReconfiguration (final int displayId , final boolean removed ) {
131
- synchronized (this ) {
132
- if (removed && devices .containsKey (displayId )) {
133
- final CGraphicsDevice gd = devices .remove (displayId );
134
- oldDevices .add (new WeakReference <>(gd ));
135
- }
136
- }
137
- initDevices ();
138
-
139
- // Need to notify old devices, in case the user hold the reference to it
140
- for (ListIterator <WeakReference <CGraphicsDevice >> it =
141
- oldDevices .listIterator (); it .hasNext (); ) {
142
- CGraphicsDevice gd = it .next ().get ();
143
- if (gd != null ) {
144
- gd .invalidate (mainDisplayID );
145
- gd .displayChanged ();
146
- } else {
147
- // no more references to this device, remove it
148
- it .remove ();
149
- }
150
- }
137
+ void _displayReconfiguration (int displayId , boolean removed ) {
138
+ // we ignore the passed parameters and check removed devices ourself
139
+ // Note that it is possible that this callback is called when the
140
+ // monitors are not added nor removed, but when the video card is
141
+ // switched to/from the discrete video card, so we should try to map the
142
+ // old to the new devices.
143
+ rebuildDevices ();
151
144
}
152
145
153
146
@ Override
@@ -163,44 +156,74 @@ protected void finalize() throws Throwable {
163
156
/**
164
157
* (Re)create all CGraphicsDevices, reuses a devices if it is possible.
165
158
*/
166
- private void initDevices () {
167
- synchronized (this ) {
168
- final Map <Integer , CGraphicsDevice > old = new HashMap <>(devices );
169
- devices .clear ();
170
-
171
- mainDisplayID = getMainDisplayID ();
172
-
173
- // initialization of the graphics device may change
174
- // list of displays on hybrid systems via an activation
175
- // of discrete video.
176
- // So, we initialize the main display first, and then
177
- // retrieve actual list of displays.
178
- if (!old .containsKey (mainDisplayID )) {
179
- old .put (mainDisplayID , new CGraphicsDevice (mainDisplayID ));
159
+ private synchronized void initDevices () {
160
+ Map <Integer , CGraphicsDevice > old = new HashMap <>(devices );
161
+ devices .clear ();
162
+ mainDisplayID = getMainDisplayID ();
163
+
164
+ // initialization of the graphics device may change list of displays on
165
+ // hybrid systems via an activation of discrete video.
166
+ // So, we initialize the main display first, then retrieve actual list
167
+ // of displays, and then recheck the main display again.
168
+ if (!old .containsKey (mainDisplayID )) {
169
+ old .put (mainDisplayID , new CGraphicsDevice (mainDisplayID ));
170
+ }
171
+
172
+ int [] displayIDs = getDisplayIDs ();
173
+ if (displayIDs .length == 0 ) {
174
+ // we could throw AWTError in this case.
175
+ displayIDs = new int []{mainDisplayID };
176
+ }
177
+ for (int id : displayIDs ) {
178
+ devices .put (id , old .containsKey (id ) ? old .remove (id )
179
+ : new CGraphicsDevice (id ));
180
+ }
181
+ // fetch the main display again, the old value might be outdated
182
+ mainDisplayID = getMainDisplayID ();
183
+
184
+ // unlikely but make sure the main screen is in the list of screens,
185
+ // most probably one more "displayReconfiguration" is on the road if not
186
+ if (!devices .containsKey (mainDisplayID )) {
187
+ mainDisplayID = displayIDs [0 ]; // best we can do
188
+ }
189
+ // if a device was not reused it should be invalidated
190
+ for (CGraphicsDevice gd : old .values ()) {
191
+ oldDevices .add (new WeakReference <>(gd ));
192
+ }
193
+ // Need to notify old devices, in case the user hold the reference to it
194
+ for (ListIterator <WeakReference <CGraphicsDevice >> it =
195
+ oldDevices .listIterator (); it .hasNext (); ) {
196
+ CGraphicsDevice gd = it .next ().get ();
197
+ if (gd != null ) {
198
+ // If the old device has the same bounds as some new device
199
+ // then map that old device to the new, or to the main screen.
200
+ CGraphicsDevice similarDevice = getSimilarDevice (gd );
201
+ if (similarDevice == null ) {
202
+ gd .invalidate (devices .get (mainDisplayID ));
203
+ } else {
204
+ gd .invalidate (similarDevice );
205
+ }
206
+ gd .displayChanged ();
207
+ } else {
208
+ // no more references to this device, remove it
209
+ it .remove ();
180
210
}
211
+ }
212
+ }
181
213
182
- for (final int id : getDisplayIDs ()) {
183
- devices .put (id , old .containsKey (id ) ? old .get (id )
184
- : new CGraphicsDevice (id ));
214
+ private CGraphicsDevice getSimilarDevice (CGraphicsDevice old ) {
215
+ for (CGraphicsDevice device : devices .values ()) {
216
+ if (device .getBounds ().equals (old .getBounds ())) {
217
+ // for now we will use the bounds only
218
+ return device ;
185
219
}
186
220
}
187
- displayChanged () ;
221
+ return null ;
188
222
}
189
223
190
224
@ Override
191
225
public synchronized GraphicsDevice getDefaultScreenDevice () throws HeadlessException {
192
- CGraphicsDevice d = devices .get (mainDisplayID );
193
- if (d == null ) {
194
- // we do not expect that this may happen, the only response
195
- // is to re-initialize the list of devices
196
- initDevices ();
197
-
198
- d = devices .get (mainDisplayID );
199
- if (d == null ) {
200
- throw new AWTError ("no screen devices" );
201
- }
202
- }
203
- return d ;
226
+ return devices .get (mainDisplayID );
204
227
}
205
228
206
229
@ Override
0 commit comments