Path: blob/master/src/java.desktop/share/classes/sun/awt/SunDisplayChanger.java
41152 views
/*1* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.awt;2627import java.awt.IllegalComponentStateException;28import java.util.Collections;29import java.util.Iterator;30import java.util.HashMap;31import java.util.HashSet;32import java.util.Map;33import java.util.Set;34import java.util.WeakHashMap;3536import sun.util.logging.PlatformLogger;3738/**39* This class is used to aid in keeping track of DisplayChangedListeners and40* notifying them when a display change has taken place. DisplayChangedListeners41* are notified when the display's bit depth is changed, or when a top-level42* window has been dragged onto another screen.43*44* It is safe for a DisplayChangedListener to be added while the list is being45* iterated.46*47* The displayChanged() call is propagated after some occurrence (either48* due to user action or some other application) causes the display mode49* (e.g., depth or resolution) to change. All heavyweight components need50* to know when this happens because they need to create new surfaceData51* objects based on the new depth.52*53* displayChanged() is also called on Windows when they are moved from one54* screen to another on a system equipped with multiple displays.55*/56public class SunDisplayChanger {5758private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.multiscreen.SunDisplayChanger");5960// Create a new synchronized map with initial capacity of one listener.61// It is asserted that the most common case is to have one GraphicsDevice62// and one top-level Window.63private Map<DisplayChangedListener, Void> listeners =64Collections.synchronizedMap(new WeakHashMap<DisplayChangedListener, Void>(1));6566public SunDisplayChanger() {}6768/*69* Add a DisplayChangeListener to this SunDisplayChanger so that it is70* notified when the display is changed.71*/72public void add(DisplayChangedListener theListener) {73if (log.isLoggable(PlatformLogger.Level.FINE)) {74if (theListener == null) {75log.fine("Assertion (theListener != null) failed");76}77}78if (log.isLoggable(PlatformLogger.Level.FINER)) {79log.finer("Adding listener: " + theListener);80}81listeners.put(theListener, null);82}8384/*85* Remove the given DisplayChangeListener from this SunDisplayChanger.86*/87public void remove(DisplayChangedListener theListener) {88if (log.isLoggable(PlatformLogger.Level.FINE)) {89if (theListener == null) {90log.fine("Assertion (theListener != null) failed");91}92}93if (log.isLoggable(PlatformLogger.Level.FINER)) {94log.finer("Removing listener: " + theListener);95}96listeners.remove(theListener);97}9899/*100* Notify our list of DisplayChangedListeners that a display change has101* taken place by calling their displayChanged() methods.102*/103public void notifyListeners() {104if (log.isLoggable(PlatformLogger.Level.FINEST)) {105log.finest("notifyListeners");106}107// This method is implemented by making a clone of the set of listeners,108// and then iterating over the clone. This is because during the course109// of responding to a display change, it may be appropriate for a110// DisplayChangedListener to add or remove itself from a SunDisplayChanger.111// If the set itself were iterated over, rather than a clone, it is112// trivial to get a ConcurrentModificationException by having a113// DisplayChangedListener remove itself from its list.114// Because all display change handling is done on the event thread,115// synchronization provides no protection against modifying the listener116// list while in the middle of iterating over it. -bchristi 7/10/2001117118Set<DisplayChangedListener> cloneSet;119120synchronized(listeners) {121cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());122}123124for (DisplayChangedListener current : cloneSet) {125try {126if (log.isLoggable(PlatformLogger.Level.FINEST)) {127log.finest("displayChanged for listener: " + current);128}129current.displayChanged();130} catch (IllegalComponentStateException e) {131// This DisplayChangeListener is no longer valid. Most132// likely, a top-level window was dispose()d, but its133// Java objects have not yet been garbage collected. In any134// case, we no longer need to track this listener, though we135// do need to remove it from the original list, not the clone.136listeners.remove(current);137}138}139}140141/*142* Notify our list of DisplayChangedListeners that a palette change has143* taken place by calling their paletteChanged() methods.144*/145public void notifyPaletteChanged() {146if (log.isLoggable(PlatformLogger.Level.FINEST)) {147log.finest("notifyPaletteChanged");148}149// This method is implemented by making a clone of the set of listeners,150// and then iterating over the clone. This is because during the course151// of responding to a display change, it may be appropriate for a152// DisplayChangedListener to add or remove itself from a SunDisplayChanger.153// If the set itself were iterated over, rather than a clone, it is154// trivial to get a ConcurrentModificationException by having a155// DisplayChangedListener remove itself from its list.156// Because all display change handling is done on the event thread,157// synchronization provides no protection against modifying the listener158// list while in the middle of iterating over it. -bchristi 7/10/2001159160Set<DisplayChangedListener> cloneSet;161162synchronized (listeners) {163cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());164}165for (DisplayChangedListener current : cloneSet) {166try {167if (log.isLoggable(PlatformLogger.Level.FINEST)) {168log.finest("paletteChanged for listener: " + current);169}170current.paletteChanged();171} catch (IllegalComponentStateException e) {172// This DisplayChangeListener is no longer valid. Most173// likely, a top-level window was dispose()d, but its174// Java objects have not yet been garbage collected. In any175// case, we no longer need to track this listener, though we176// do need to remove it from the original list, not the clone.177listeners.remove(current);178}179}180}181}182183184