src/share/classes/sun/awt/SunDisplayChanger.java

Print this page




  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.IllegalComponentStateException;
  29 import java.util.Collections;
  30 import java.util.Iterator;


  31 import java.util.Map;
  32 import java.util.Set;
  33 import java.util.HashMap;
  34 import java.util.WeakHashMap;
  35 
  36 import sun.util.logging.PlatformLogger;
  37 
  38 /**
  39  * This class is used to aid in keeping track of DisplayChangedListeners and
  40  * notifying them when a display change has taken place. DisplayChangedListeners
  41  * are notified when the display's bit depth is changed, or when a top-level
  42  * window has been dragged onto another screen.
  43  *
  44  * It is safe for a DisplayChangedListener to be added while the list is being
  45  * iterated.
  46  *
  47  * The displayChanged() call is propagated after some occurrence (either
  48  * due to user action or some other application) causes the display mode
  49  * (e.g., depth or resolution) to change.  All heavyweight components need
  50  * to know when this happens because they need to create new surfaceData
  51  * objects based on the new depth.
  52  *
  53  * displayChanged() is also called on Windows when they are moved from one
  54  * screen to another on a system equipped with multiple displays.
  55  */
  56 public class SunDisplayChanger {

  57     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.multiscreen.SunDisplayChanger");
  58 
  59     // Create a new synchronizedMap with initial capacity of one listener.
  60     // It is asserted that the most common case is to have one GraphicsDevice
  61     // and one top-level Window.
  62     private Map listeners = Collections.synchronizedMap(new WeakHashMap(1));

  63 
  64     public SunDisplayChanger() {}
  65 
  66     /*
  67      * Add a DisplayChangeListener to this SunDisplayChanger so that it is
  68      * notified when the display is changed.
  69      */
  70     public void add(DisplayChangedListener theListener) {
  71         if (log.isLoggable(PlatformLogger.FINE)) {
  72             if (theListener == null) {
  73                 log.fine("Assertion (theListener != null) failed");
  74             }
  75         }
  76         if (log.isLoggable(PlatformLogger.FINER)) {
  77             log.finer("Adding listener: " + theListener);
  78         }
  79         listeners.put(theListener, null);
  80     }
  81 
  82     /*


  96 
  97     /*
  98      * Notify our list of DisplayChangedListeners that a display change has
  99      * taken place by calling their displayChanged() methods.
 100      */
 101     public void notifyListeners() {
 102         if (log.isLoggable(PlatformLogger.FINEST)) {
 103             log.finest("notifyListeners");
 104         }
 105     // This method is implemented by making a clone of the set of listeners,
 106     // and then iterating over the clone.  This is because during the course
 107     // of responding to a display change, it may be appropriate for a
 108     // DisplayChangedListener to add or remove itself from a SunDisplayChanger.
 109     // If the set itself were iterated over, rather than a clone, it is
 110     // trivial to get a ConcurrentModificationException by having a
 111     // DisplayChangedListener remove itself from its list.
 112     // Because all display change handling is done on the event thread,
 113     // synchronization provides no protection against modifying the listener
 114     // list while in the middle of iterating over it.  -bchristi 7/10/2001
 115 
 116         HashMap listClone;
 117         Set cloneSet;
 118 
 119         synchronized(listeners) {
 120             listClone = new HashMap(listeners);
 121         }
 122 
 123         cloneSet = listClone.keySet();
 124         Iterator itr = cloneSet.iterator();
 125         while (itr.hasNext()) {
 126             DisplayChangedListener current =
 127              (DisplayChangedListener) itr.next();
 128             try {
 129                 if (log.isLoggable(PlatformLogger.FINEST)) {
 130                     log.finest("displayChanged for listener: " + current);
 131                 }
 132                 current.displayChanged();
 133             } catch (IllegalComponentStateException e) {
 134                 // This DisplayChangeListener is no longer valid.  Most
 135                 // likely, a top-level window was dispose()d, but its
 136                 // Java objects have not yet been garbage collected.  In any
 137                 // case, we no longer need to track this listener, though we
 138                 // do need to remove it from the original list, not the clone.
 139                 listeners.remove(current);
 140             }
 141         }
 142     }
 143 
 144     /*
 145      * Notify our list of DisplayChangedListeners that a palette change has
 146      * taken place by calling their paletteChanged() methods.
 147      */
 148     public void notifyPaletteChanged() {
 149         if (log.isLoggable(PlatformLogger.FINEST)) {
 150             log.finest("notifyPaletteChanged");
 151         }
 152     // This method is implemented by making a clone of the set of listeners,
 153     // and then iterating over the clone.  This is because during the course
 154     // of responding to a display change, it may be appropriate for a
 155     // DisplayChangedListener to add or remove itself from a SunDisplayChanger.
 156     // If the set itself were iterated over, rather than a clone, it is
 157     // trivial to get a ConcurrentModificationException by having a
 158     // DisplayChangedListener remove itself from its list.
 159     // Because all display change handling is done on the event thread,
 160     // synchronization provides no protection against modifying the listener
 161     // list while in the middle of iterating over it.  -bchristi 7/10/2001
 162 
 163         HashMap listClone;
 164         Set cloneSet;
 165 
 166         synchronized (listeners) {
 167             listClone = new HashMap(listeners);
 168         }
 169         cloneSet = listClone.keySet();
 170         Iterator itr = cloneSet.iterator();
 171         while (itr.hasNext()) {
 172             DisplayChangedListener current =
 173              (DisplayChangedListener) itr.next();
 174             try {
 175                 if (log.isLoggable(PlatformLogger.FINEST)) {
 176                     log.finest("paletteChanged for listener: " + current);
 177                 }
 178                 current.paletteChanged();
 179             } catch (IllegalComponentStateException e) {
 180                 // This DisplayChangeListener is no longer valid.  Most
 181                 // likely, a top-level window was dispose()d, but its
 182                 // Java objects have not yet been garbage collected.  In any
 183                 // case, we no longer need to track this listener, though we
 184                 // do need to remove it from the original list, not the clone.
 185                 listeners.remove(current);
 186             }
 187         }
 188     }
 189 }


  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.IllegalComponentStateException;
  29 import java.util.Collections;
  30 import java.util.Iterator;
  31 import java.util.HashMap;
  32 import java.util.HashSet;
  33 import java.util.Map;
  34 import java.util.Set;

  35 import java.util.WeakHashMap;
  36 
  37 import sun.util.logging.PlatformLogger;
  38 
  39 /**
  40  * This class is used to aid in keeping track of DisplayChangedListeners and
  41  * notifying them when a display change has taken place. DisplayChangedListeners
  42  * are notified when the display's bit depth is changed, or when a top-level
  43  * window has been dragged onto another screen.
  44  *
  45  * It is safe for a DisplayChangedListener to be added while the list is being
  46  * iterated.
  47  *
  48  * The displayChanged() call is propagated after some occurrence (either
  49  * due to user action or some other application) causes the display mode
  50  * (e.g., depth or resolution) to change.  All heavyweight components need
  51  * to know when this happens because they need to create new surfaceData
  52  * objects based on the new depth.
  53  *
  54  * displayChanged() is also called on Windows when they are moved from one
  55  * screen to another on a system equipped with multiple displays.
  56  */
  57 public class SunDisplayChanger {
  58 
  59     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.multiscreen.SunDisplayChanger");
  60 
  61     // Create a new synchronized map with initial capacity of one listener.
  62     // It is asserted that the most common case is to have one GraphicsDevice
  63     // and one top-level Window.
  64     private Map<DisplayChangedListener, Void> listeners =
  65         Collections.synchronizedMap(new WeakHashMap<DisplayChangedListener, Void>(1));
  66 
  67     public SunDisplayChanger() {}
  68 
  69     /*
  70      * Add a DisplayChangeListener to this SunDisplayChanger so that it is
  71      * notified when the display is changed.
  72      */
  73     public void add(DisplayChangedListener theListener) {
  74         if (log.isLoggable(PlatformLogger.FINE)) {
  75             if (theListener == null) {
  76                 log.fine("Assertion (theListener != null) failed");
  77             }
  78         }
  79         if (log.isLoggable(PlatformLogger.FINER)) {
  80             log.finer("Adding listener: " + theListener);
  81         }
  82         listeners.put(theListener, null);
  83     }
  84 
  85     /*


  99 
 100     /*
 101      * Notify our list of DisplayChangedListeners that a display change has
 102      * taken place by calling their displayChanged() methods.
 103      */
 104     public void notifyListeners() {
 105         if (log.isLoggable(PlatformLogger.FINEST)) {
 106             log.finest("notifyListeners");
 107         }
 108     // This method is implemented by making a clone of the set of listeners,
 109     // and then iterating over the clone.  This is because during the course
 110     // of responding to a display change, it may be appropriate for a
 111     // DisplayChangedListener to add or remove itself from a SunDisplayChanger.
 112     // If the set itself were iterated over, rather than a clone, it is
 113     // trivial to get a ConcurrentModificationException by having a
 114     // DisplayChangedListener remove itself from its list.
 115     // Because all display change handling is done on the event thread,
 116     // synchronization provides no protection against modifying the listener
 117     // list while in the middle of iterating over it.  -bchristi 7/10/2001
 118 
 119         Set<DisplayChangedListener> cloneSet;

 120 
 121         synchronized(listeners) {
 122             cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());
 123         }
 124 
 125         Iterator<DisplayChangedListener> itr = cloneSet.iterator();

 126         while (itr.hasNext()) {
 127             DisplayChangedListener current = itr.next();

 128             try {
 129                 if (log.isLoggable(PlatformLogger.FINEST)) {
 130                     log.finest("displayChanged for listener: " + current);
 131                 }
 132                 current.displayChanged();
 133             } catch (IllegalComponentStateException e) {
 134                 // This DisplayChangeListener is no longer valid.  Most
 135                 // likely, a top-level window was dispose()d, but its
 136                 // Java objects have not yet been garbage collected.  In any
 137                 // case, we no longer need to track this listener, though we
 138                 // do need to remove it from the original list, not the clone.
 139                 listeners.remove(current);
 140             }
 141         }
 142     }
 143 
 144     /*
 145      * Notify our list of DisplayChangedListeners that a palette change has
 146      * taken place by calling their paletteChanged() methods.
 147      */
 148     public void notifyPaletteChanged() {
 149         if (log.isLoggable(PlatformLogger.FINEST)) {
 150             log.finest("notifyPaletteChanged");
 151         }
 152     // This method is implemented by making a clone of the set of listeners,
 153     // and then iterating over the clone.  This is because during the course
 154     // of responding to a display change, it may be appropriate for a
 155     // DisplayChangedListener to add or remove itself from a SunDisplayChanger.
 156     // If the set itself were iterated over, rather than a clone, it is
 157     // trivial to get a ConcurrentModificationException by having a
 158     // DisplayChangedListener remove itself from its list.
 159     // Because all display change handling is done on the event thread,
 160     // synchronization provides no protection against modifying the listener
 161     // list while in the middle of iterating over it.  -bchristi 7/10/2001
 162 
 163         Set<DisplayChangedListener> cloneSet;

 164 
 165         synchronized (listeners) {
 166             cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());
 167         }
 168         Iterator<DisplayChangedListener> itr = cloneSet.iterator();

 169         while (itr.hasNext()) {
 170             DisplayChangedListener current = itr.next();

 171             try {
 172                 if (log.isLoggable(PlatformLogger.FINEST)) {
 173                     log.finest("paletteChanged for listener: " + current);
 174                 }
 175                 current.paletteChanged();
 176             } catch (IllegalComponentStateException e) {
 177                 // This DisplayChangeListener is no longer valid.  Most
 178                 // likely, a top-level window was dispose()d, but its
 179                 // Java objects have not yet been garbage collected.  In any
 180                 // case, we no longer need to track this listener, though we
 181                 // do need to remove it from the original list, not the clone.
 182                 listeners.remove(current);
 183             }
 184         }
 185     }
 186 }