Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/awt/SunDisplayChanger.java
38827 views
/*1* Copyright (c) 2000, 2013, 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}123124Iterator<DisplayChangedListener> itr = cloneSet.iterator();125while (itr.hasNext()) {126DisplayChangedListener current = itr.next();127try {128if (log.isLoggable(PlatformLogger.Level.FINEST)) {129log.finest("displayChanged for listener: " + current);130}131current.displayChanged();132} catch (IllegalComponentStateException e) {133// This DisplayChangeListener is no longer valid. Most134// likely, a top-level window was dispose()d, but its135// Java objects have not yet been garbage collected. In any136// case, we no longer need to track this listener, though we137// do need to remove it from the original list, not the clone.138listeners.remove(current);139}140}141}142143/*144* Notify our list of DisplayChangedListeners that a palette change has145* taken place by calling their paletteChanged() methods.146*/147public void notifyPaletteChanged() {148if (log.isLoggable(PlatformLogger.Level.FINEST)) {149log.finest("notifyPaletteChanged");150}151// This method is implemented by making a clone of the set of listeners,152// and then iterating over the clone. This is because during the course153// of responding to a display change, it may be appropriate for a154// DisplayChangedListener to add or remove itself from a SunDisplayChanger.155// If the set itself were iterated over, rather than a clone, it is156// trivial to get a ConcurrentModificationException by having a157// DisplayChangedListener remove itself from its list.158// Because all display change handling is done on the event thread,159// synchronization provides no protection against modifying the listener160// list while in the middle of iterating over it. -bchristi 7/10/2001161162Set<DisplayChangedListener> cloneSet;163164synchronized (listeners) {165cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());166}167Iterator<DisplayChangedListener> itr = cloneSet.iterator();168while (itr.hasNext()) {169DisplayChangedListener current = itr.next();170try {171if (log.isLoggable(PlatformLogger.Level.FINEST)) {172log.finest("paletteChanged for listener: " + current);173}174current.paletteChanged();175} catch (IllegalComponentStateException e) {176// This DisplayChangeListener is no longer valid. Most177// likely, a top-level window was dispose()d, but its178// Java objects have not yet been garbage collected. In any179// case, we no longer need to track this listener, though we180// do need to remove it from the original list, not the clone.181listeners.remove(current);182}183}184}185}186187188