changeset 1103:66d6db0a1de6

6804747: Ensure consistent graphicsConfig member across components hierarchy Reviewed-by: art, dcherepanov
author anthony
date Fri, 20 Feb 2009 17:34:16 +0300
parents 2083f9461cea
children b22974c82ca8
files src/share/classes/java/awt/Canvas.java src/share/classes/java/awt/Component.java src/share/classes/java/awt/Container.java src/share/classes/java/awt/Window.java src/share/classes/java/awt/peer/CanvasPeer.java src/share/classes/java/awt/peer/ComponentPeer.java src/share/classes/sun/awt/AWTAccessor.java src/share/classes/sun/awt/ComponentAccessor.java src/share/classes/sun/awt/NullComponentPeer.java src/solaris/classes/sun/awt/X11/XCanvasPeer.java src/solaris/classes/sun/awt/X11/XComponentPeer.java src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java src/solaris/classes/sun/awt/X11/XPanelPeer.java src/solaris/classes/sun/awt/X11/XWindowPeer.java src/solaris/native/sun/awt/awt_Component.h src/solaris/native/sun/awt/awt_Window.h src/solaris/native/sun/xawt/XToolkit.c src/windows/classes/sun/awt/Win32GraphicsDevice.java src/windows/classes/sun/awt/windows/WCanvasPeer.java src/windows/classes/sun/awt/windows/WComponentPeer.java src/windows/classes/sun/awt/windows/WPanelPeer.java src/windows/classes/sun/awt/windows/WWindowPeer.java
diffstat 22 files changed, 190 insertions(+), 304 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/awt/Canvas.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/java/awt/Canvas.java	Fri Feb 20 17:34:16 2009 +0300
@@ -25,6 +25,7 @@
 package java.awt;
 
 import java.awt.image.BufferStrategy;
+import java.awt.peer.CanvasPeer;
 import javax.accessibility.*;
 
 /**
@@ -65,7 +66,17 @@
      */
     public Canvas(GraphicsConfiguration config) {
         this();
-        graphicsConfig = config;
+        setGraphicsConfiguration(config);
+    }
+
+    @Override
+    void setGraphicsConfiguration(GraphicsConfiguration gc) {
+        CanvasPeer peer = (CanvasPeer)getPeer();
+        if (peer != null) {
+            gc = peer.getAppropriateGraphicsConfiguration(gc);
+        }
+
+        super.setGraphicsConfiguration(gc);
     }
 
     /**
--- a/src/share/classes/java/awt/Component.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/java/awt/Component.java	Fri Feb 20 17:34:16 2009 +0300
@@ -300,7 +300,7 @@
      * @see GraphicsConfiguration
      * @see #getGraphicsConfiguration
      */
-    transient GraphicsConfiguration graphicsConfig = null;
+    private transient GraphicsConfiguration graphicsConfig = null;
 
     /**
      * A reference to a <code>BufferStrategy</code> object
@@ -845,6 +845,12 @@
                     }
                 }
             }
+
+            public void setGraphicsConfiguration(Component comp,
+                    GraphicsConfiguration gc)
+            {
+                comp.setGraphicsConfiguration(gc);
+            }
         });
     }
 
@@ -1012,50 +1018,21 @@
      */
     public GraphicsConfiguration getGraphicsConfiguration() {
         synchronized(getTreeLock()) {
-            if (graphicsConfig != null) {
-                return graphicsConfig;
-            } else if (getParent() != null) {
-                return getParent().getGraphicsConfiguration();
-            } else {
-                return null;
-            }
+            return getGraphicsConfiguration_NoClientCode();
         }
     }
 
     final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() {
-        GraphicsConfiguration graphicsConfig = this.graphicsConfig;
-        Container parent = this.parent;
-        if (graphicsConfig != null) {
-            return graphicsConfig;
-        } else if (parent != null) {
-            return parent.getGraphicsConfiguration_NoClientCode();
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Resets this <code>Component</code>'s
-     * <code>GraphicsConfiguration</code> back to a default
-     * value.  For most componenets, this is <code>null</code>.
-     * Called from the Toolkit thread, so NO CLIENT CODE.
-     */
-    void resetGC() {
+        return graphicsConfig;
+    }
+
+    void setGraphicsConfiguration(GraphicsConfiguration gc) {
         synchronized(getTreeLock()) {
-            graphicsConfig = null;
-        }
-    }
-
-    /*
-     * Not called on Component, but needed for Canvas and Window
-     */
-    void setGCFromPeer() {
-        synchronized(getTreeLock()) {
-            if (peer != null) { // can't imagine how this will be false,
-                                // but just in case
-                graphicsConfig = peer.getGraphicsConfiguration();
-            } else {
-                graphicsConfig = null;
+            graphicsConfig = gc;
+
+            ComponentPeer peer = getPeer();
+            if (peer != null) {
+                peer.updateGraphicsData(gc);
             }
         }
     }
--- a/src/share/classes/java/awt/Container.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/java/awt/Container.java	Fri Feb 20 17:34:16 2009 +0300
@@ -506,6 +506,7 @@
             adjustDescendants(-(comp.countHierarchyMembers()));
 
             comp.parent = null;
+            comp.setGraphicsConfiguration(null);
             component.remove(index);
 
             invalidateIfValid();
@@ -789,6 +790,7 @@
                 component.add(index, comp);
             }
             comp.parent = this;
+            comp.setGraphicsConfiguration(getGraphicsConfiguration());
 
             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
                                     comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
@@ -1056,6 +1058,7 @@
                 component.add(index, comp);
             }
             comp.parent = this;
+            comp.setGraphicsConfiguration(thisGC);
 
             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
                 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
@@ -1094,6 +1097,19 @@
         }
     }
 
+    @Override
+    void setGraphicsConfiguration(GraphicsConfiguration gc) {
+        synchronized (getTreeLock()) {
+            super.setGraphicsConfiguration(gc);
+
+            for (Component comp : component) {
+                if (comp != null) {
+                    comp.setGraphicsConfiguration(gc);
+                }
+            }
+        }
+    }
+
     /**
      * Checks that all Components that this Container contains are on
      * the same GraphicsDevice as this Container.  If not, throws an
@@ -1151,6 +1167,7 @@
 
             comp.parent = null;
             component.remove(index);
+            comp.setGraphicsConfiguration(null);
 
             invalidateIfValid();
             if (containerListener != null ||
@@ -1227,6 +1244,7 @@
                     layoutMgr.removeLayoutComponent(comp);
                 }
                 comp.parent = null;
+                comp.setGraphicsConfiguration(null);
                 if (containerListener != null ||
                    (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                     Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
--- a/src/share/classes/java/awt/Window.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/java/awt/Window.java	Fri Feb 20 17:34:16 2009 +0300
@@ -394,6 +394,18 @@
         }
     }
 
+    private GraphicsConfiguration initGC(GraphicsConfiguration gc) {
+        GraphicsEnvironment.checkHeadless();
+
+        if (gc == null) {
+            gc = GraphicsEnvironment.getLocalGraphicsEnvironment().
+                getDefaultScreenDevice().getDefaultConfiguration();
+        }
+        setGraphicsConfiguration(gc);
+
+        return gc;
+    }
+
     private void init(GraphicsConfiguration gc) {
         GraphicsEnvironment.checkHeadless();
 
@@ -405,14 +417,10 @@
         setWarningString();
         this.cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
         this.visible = false;
-        if (gc == null) {
-            this.graphicsConfig =
-                GraphicsEnvironment.getLocalGraphicsEnvironment().
-             getDefaultScreenDevice().getDefaultConfiguration();
-        } else {
-            this.graphicsConfig = gc;
-        }
-        if (graphicsConfig.getDevice().getType() !=
+
+        gc = initGC(gc);
+
+        if (gc.getDevice().getType() !=
             GraphicsDevice.TYPE_RASTER_SCREEN) {
             throw new IllegalArgumentException("not a screen device");
         }
@@ -420,8 +428,8 @@
 
         /* offset the initial location with the original of the screen */
         /* and any insets                                              */
-        Rectangle screenBounds = graphicsConfig.getBounds();
-        Insets screenInsets = getToolkit().getScreenInsets(graphicsConfig);
+        Rectangle screenBounds = gc.getBounds();
+        Insets screenInsets = getToolkit().getScreenInsets(gc);
         int x = getX() + screenBounds.x + screenInsets.left;
         int y = getY() + screenBounds.y + screenInsets.top;
         if (x != this.x || y != this.y) {
@@ -2765,7 +2773,7 @@
         sun.java2d.Disposer.addRecord(anchor, new WindowDisposerRecord(appContext, this));
 
         addToWindowList();
-
+        initGC(null);
     }
 
     private void deserializeResources(ObjectInputStream s)
@@ -2939,41 +2947,18 @@
 
     } // inner class AccessibleAWTWindow
 
-    /**
-     * This method returns the GraphicsConfiguration used by this Window.
-     * @since 1.3
-     */
-    public GraphicsConfiguration getGraphicsConfiguration() {
-                //NOTE: for multiscreen, this will need to take into account
-                //which screen the window is on/mostly on instead of returning the
-                //default or constructor argument config.
-        synchronized(getTreeLock()) {
-            if (graphicsConfig == null  && !GraphicsEnvironment.isHeadless()) {
-                graphicsConfig =
-                    GraphicsEnvironment. getLocalGraphicsEnvironment().
-                    getDefaultScreenDevice().
-                    getDefaultConfiguration();
-            }
-            return graphicsConfig;
-            }
-    }
-
-    /**
-     * Reset this Window's GraphicsConfiguration to match its peer.
-     */
-    void resetGC() {
-        if (!GraphicsEnvironment.isHeadless()) {
-            // use the peer's GC
-            setGCFromPeer();
-            // if it's still null, use the default
-            if (graphicsConfig == null) {
-                graphicsConfig = GraphicsEnvironment.
+    @Override
+    void setGraphicsConfiguration(GraphicsConfiguration gc) {
+        if (gc == null) {
+            gc = GraphicsEnvironment.
                     getLocalGraphicsEnvironment().
                     getDefaultScreenDevice().
                     getDefaultConfiguration();
-            }
+        }
+        synchronized (getTreeLock()) {
+            super.setGraphicsConfiguration(gc);
             if (log.isLoggable(Level.FINER)) {
-                log.finer("+ Window.resetGC(): new GC is \n+ " + graphicsConfig + "\n+ this is " + this);
+                log.finer("+ Window.setGraphicsConfiguration(): new GC is \n+ " + getGraphicsConfiguration_NoClientCode() + "\n+ this is " + this);
             }
         }
     }
@@ -3033,7 +3018,7 @@
         // target location
         int dx = 0, dy = 0;
         // target GC
-        GraphicsConfiguration gc = this.graphicsConfig;
+        GraphicsConfiguration gc = getGraphicsConfiguration_NoClientCode();
         Rectangle gcBounds = gc.getBounds();
 
         Dimension windowSize = getSize();
--- a/src/share/classes/java/awt/peer/CanvasPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/java/awt/peer/CanvasPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -25,6 +25,7 @@
 package java.awt.peer;
 
 import java.awt.Canvas;
+import java.awt.GraphicsConfiguration;
 
 /**
  * The peer interface for {@link Canvas}.
@@ -36,4 +37,13 @@
  * instances.
  */
 public interface CanvasPeer extends ComponentPeer {
+    /**
+     * Requests a GC that best suits this Canvas. The returned GC may differ
+     * from the requested GC passed as the argument to this method. This method
+     * must return a non-null value (given the argument is non-null as well).
+     *
+     * @since 1.7
+     */
+    GraphicsConfiguration getAppropriateGraphicsConfiguration(
+            GraphicsConfiguration gc);
 }
--- a/src/share/classes/java/awt/peer/ComponentPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/java/awt/peer/ComponentPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -539,4 +539,10 @@
      */
     void applyShape(Region shape);
 
+    /**
+     * Updates internal data structures related to the component's GC.
+     *
+     * @since 1.7
+     */
+    void updateGraphicsData(GraphicsConfiguration gc);
 }
--- a/src/share/classes/sun/awt/AWTAccessor.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/sun/awt/AWTAccessor.java	Fri Feb 20 17:34:16 2009 +0300
@@ -78,6 +78,11 @@
          * See 6797587, 6776743, 6768307, and 6768332 for details
          */
         void setMixingCutoutShape(Component comp, Shape shape);
+
+        /**
+         * Sets GraphicsConfiguration value for the component.
+         */
+        void setGraphicsConfiguration(Component comp, GraphicsConfiguration gc);
     }
 
     /*
--- a/src/share/classes/sun/awt/ComponentAccessor.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/sun/awt/ComponentAccessor.java	Fri Feb 20 17:34:16 2009 +0300
@@ -73,7 +73,6 @@
     private static Field fieldPacked;
     private static Field fieldIgnoreRepaint;
     private static Field fieldPeer;
-    private static Method methodResetGC;
     private static Field fieldVisible;
     private static Method methodIsEnabledImpl;
     private static Method methodGetCursorNoClientCode;
@@ -124,9 +123,6 @@
                         fieldPeer = componentClass.getDeclaredField("peer");
                         fieldPeer.setAccessible(true);
 
-                        methodResetGC = componentClass.getDeclaredMethod("resetGC", (Class[]) null);
-                        methodResetGC.setAccessible(true);
-
                         fieldVisible = componentClass.getDeclaredField("visible");
                         fieldVisible.setAccessible(true);
 
@@ -425,18 +421,6 @@
         return false;
     }
 
-    public static void resetGC(Component c) {
-        try {
-            methodResetGC.invoke(c, (Object[]) null);
-        }
-        catch (IllegalAccessException e) {
-            log.log(Level.FINE, "Unable to access the Component object", e);
-        }
-        catch (InvocationTargetException e) {
-            log.log(Level.FINE, "Unable to invoke on the Component object", e);
-        }
-    }
-
     public static boolean getVisible(Component c) {
         try {
             return fieldVisible.getBoolean(c);
--- a/src/share/classes/sun/awt/NullComponentPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/share/classes/sun/awt/NullComponentPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -305,4 +305,12 @@
       */
     public void applyShape(Region shape) {
     }
+
+    public void updateGraphicsData(GraphicsConfiguration gc) {}
+
+    public GraphicsConfiguration getAppropriateGraphicsConfiguration(
+                        GraphicsConfiguration gc)
+    {
+        return gc;
+    }
 }
--- a/src/solaris/classes/sun/awt/X11/XCanvasPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XCanvasPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -27,7 +27,6 @@
 import java.awt.*;
 import java.awt.peer.*;
 
-import sun.awt.ComponentAccessor;
 import sun.awt.SunToolkit;
 
 import sun.awt.X11GraphicsConfig;
@@ -54,60 +53,45 @@
         }
     }
 
-    void resetTargetGC(Component target) {
-        ComponentAccessor.resetGC(target);
+    /* Get a GraphicsConfig with the same visual on the new
+     * screen, which should be easy in Xinerama mode.
+     */
+    public GraphicsConfiguration getAppropriateGraphicsConfiguration(
+                                    GraphicsConfiguration gc)
+    {
+        if (graphicsConfig == null || gc == null) {
+            return gc;
+        }
+        // Opt: Only need to do if we're not using the default GC
+
+        int screenNum = ((X11GraphicsDevice)gc.getDevice()).getScreen();
+
+        X11GraphicsConfig parentgc;
+        // save vis id of current gc
+        int visual = graphicsConfig.getVisual();
+
+        X11GraphicsDevice newDev = (X11GraphicsDevice) GraphicsEnvironment.
+            getLocalGraphicsEnvironment().
+            getScreenDevices()[screenNum];
+
+        for (int i = 0; i < newDev.getNumConfigs(screenNum); i++) {
+            if (visual == newDev.getConfigVisualId(i, screenNum)) {
+                // use that
+                graphicsConfig = (X11GraphicsConfig)newDev.getConfigurations()[i];
+                break;
+            }
+        }
+        // just in case...
+        if (graphicsConfig == null) {
+            graphicsConfig = (X11GraphicsConfig) GraphicsEnvironment.
+                getLocalGraphicsEnvironment().
+                getScreenDevices()[screenNum].
+                getDefaultConfiguration();
+        }
+
+        return graphicsConfig;
     }
 
-    /*
-     * Called when the Window this
-     * Canvas is on is moved onto another Xinerama screen.
-     *
-     * Canvases can be created with a non-defulat GraphicsConfiguration.  The
-     * GraphicsConfiguration needs to be changed to one on the new screen,
-     * preferably with the same visual ID.
-     *
-     * Up-called for other windows peer instances (XPanelPeer, XWindowPeer).
-     *
-     * Should only be called from the event thread.
-     */
-    public void displayChanged(int screenNum) {
-        resetLocalGC(screenNum);
-        resetTargetGC(target);
-    }
-
-    /* Set graphicsConfig to a GraphicsConfig with the same visual on the new
-     * screen, which should be easy in Xinerama mode.
-     *
-     * Should only be called from displayChanged(), and therefore only from
-     * the event thread.
-     */
-    void resetLocalGC(int screenNum) {
-        // Opt: Only need to do if we're not using the default GC
-        if (graphicsConfig != null) {
-            X11GraphicsConfig parentgc;
-            // save vis id of current gc
-            int visual = graphicsConfig.getVisual();
-
-            X11GraphicsDevice newDev = (X11GraphicsDevice) GraphicsEnvironment.
-                getLocalGraphicsEnvironment().
-                getScreenDevices()[screenNum];
-
-            for (int i = 0; i < newDev.getNumConfigs(screenNum); i++) {
-                if (visual == newDev.getConfigVisualId(i, screenNum)) {
-                    // use that
-                    graphicsConfig = (X11GraphicsConfig)newDev.getConfigurations()[i];
-                    break;
-                }
-            }
-            // just in case...
-            if (graphicsConfig == null) {
-                graphicsConfig = (X11GraphicsConfig) GraphicsEnvironment.
-                    getLocalGraphicsEnvironment().
-                    getScreenDevices()[screenNum].
-                    getDefaultConfiguration();
-            }
-        }
-    }
     protected boolean shouldFocusOnClick() {
         // Canvas should always be able to be focused by mouse clicks.
         return true;
--- a/src/solaris/classes/sun/awt/X11/XComponentPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XComponentPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -35,6 +35,7 @@
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
 import java.awt.Image;
 import java.awt.Insets;
 import java.awt.KeyboardFocusManager;
@@ -1556,4 +1557,8 @@
             }
         }
     }
+
+    public void updateGraphicsData(GraphicsConfiguration gc) {
+        initGraphicsConfiguration();
+    }
 }
--- a/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -379,4 +379,6 @@
 
     public void applyShape(Region shape) {
     }
+
+    public void updateGraphicsData(GraphicsConfiguration gc) {}
 }
--- a/src/solaris/classes/sun/awt/X11/XPanelPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XPanelPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -130,39 +130,6 @@
         return getInsets();
     }
 
-    /*
-     * This method is called from XWindowPeer.displayChanged, when
-     * the window this Panel is on is moved to the new screen, or
-     * display mode is changed.
-     *
-     * The notification is propagated to the child Canvas components.
-     * Top-level windows and other Panels are notified too as their
-     * peers are subclasses of XCanvasPeer.
-     */
-    public void displayChanged(int screenNum) {
-        super.displayChanged(screenNum);
-        displayChanged((Container)target, screenNum);
-    }
-
-    /*
-     * Recursively iterates through all the HW and LW children
-     * of the container and calls displayChanged() for HW peers.
-     * Iteration through children peers only is not enough as the
-     * displayChanged notification may not be propagated to HW
-     * components inside LW containers, see 4452373 for details.
-     */
-    private static void displayChanged(Container target, int screenNum) {
-        Component children[] = ((Container)target).getComponents();
-        for (Component child : children) {
-            ComponentPeer cpeer = child.getPeer();
-            if (cpeer instanceof XCanvasPeer) {
-                ((XCanvasPeer)cpeer).displayChanged(screenNum);
-            } else if (child instanceof Container) {
-                displayChanged((Container)child, screenNum);
-            }
-        }
-    }
-
     public void dispose() {
         if (embedder != null) {
             embedder.deinstall();
--- a/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -47,6 +47,7 @@
 import sun.awt.AWTAccessor;
 import sun.awt.ComponentAccessor;
 import sun.awt.WindowAccessor;
+import sun.awt.AWTAccessor;
 import sun.awt.DisplayChangedListener;
 import sun.awt.SunToolkit;
 import sun.awt.X11GraphicsDevice;
@@ -711,6 +712,7 @@
         int curScreenNum = ((X11GraphicsDevice)getGraphicsConfiguration().getDevice()).getScreen();
         int newScreenNum = 0;
         GraphicsDevice gds[] = XToolkit.localEnv.getScreenDevices();
+        GraphicsConfiguration newGC = null;
         Rectangle screenBounds;
 
         for (int i = 0; i < gds.length; i++) {
@@ -726,11 +728,13 @@
                 if (intAmt == area) {
                     // Completely on this screen - done!
                     newScreenNum = i;
+                    newGC = gds[i].getDefaultConfiguration();
                     break;
                 }
                 if (intAmt > largestAmt) {
                     largestAmt = intAmt;
                     newScreenNum = i;
+                    newGC = gds[i].getDefaultConfiguration();
                 }
             }
         }
@@ -738,28 +742,20 @@
             if (log.isLoggable(Level.FINEST)) {
                 log.finest("XWindowPeer: Moved to a new screen");
             }
-            draggedToNewScreen(newScreenNum);
+            executeDisplayChangedOnEDT(newGC);
         }
     }
 
-    /* Xinerama
-     * called to update our GC when dragged onto another screen
-     */
-    public void draggedToNewScreen(int screenNum) {
-        executeDisplayChangedOnEDT(screenNum);
-    }
-
     /**
      * Helper method that executes the displayChanged(screen) method on
      * the event dispatch thread.  This method is used in the Xinerama case
      * and after display mode change events.
      */
-    private void executeDisplayChangedOnEDT(final int screenNum) {
+    private void executeDisplayChangedOnEDT(final GraphicsConfiguration gc) {
         Runnable dc = new Runnable() {
             public void run() {
-                // Updates this window's GC and notifies all the children.
-                // See XPanelPeer/XCanvasPeer.displayChanged(int) for details.
-                displayChanged(screenNum);
+                AWTAccessor.getComponentAccessor().
+                    setGraphicsConfiguration((Component)target, gc);
             }
         };
         SunToolkit.executeOnEventHandlerThread((Component)target, dc);
@@ -770,9 +766,7 @@
      * X11GraphicsDevice when the display mode has been changed.
      */
     public void displayChanged() {
-        GraphicsConfiguration gc = getGraphicsConfiguration();
-        int curScreenNum = ((X11GraphicsDevice)gc.getDevice()).getScreen();
-        executeDisplayChangedOnEDT(curScreenNum);
+        executeDisplayChangedOnEDT(getGraphicsConfiguration());
     }
 
     /**
--- a/src/solaris/native/sun/awt/awt_Component.h	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/native/sun/awt/awt_Component.h	Fri Feb 20 17:34:16 2009 +0300
@@ -41,7 +41,6 @@
     jfieldID appContext;
     jmethodID getParent;
     jmethodID getLocationOnScreen;
-    jmethodID resetGCMID;
 };
 
 /* field and method IDs for Container */
@@ -65,7 +64,3 @@
 extern void processTree(Widget from, Widget to, Boolean action);
 #endif // HEADLESS
 
-/* fieldIDs for Canvas fields that may be accessed from C */
-struct CanvasIDs {
-    jmethodID setGCFromPeerMID;
-};
--- a/src/solaris/native/sun/awt/awt_Window.h	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/native/sun/awt/awt_Window.h	Fri Feb 20 17:34:16 2009 +0300
@@ -28,7 +28,6 @@
 /* fieldIDs for Window fields that may be accessed from C */
 struct WindowIDs {
     jfieldID warningString;
-    jmethodID resetGCMID;
     jfieldID locationByPlatform;
     jfieldID isAutoRequestFocus;
 };
--- a/src/solaris/native/sun/xawt/XToolkit.c	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/solaris/native/sun/xawt/XToolkit.c	Fri Feb 20 17:34:16 2009 +0300
@@ -182,9 +182,6 @@
       (*env)->GetMethodID(env, cls, "getLocationOnScreen_NoTreeLock",
                          "()Ljava/awt/Point;");
 
-    componentIDs.resetGCMID =
-      (*env)->GetMethodID(env, cls, "resetGC", "()V");
-
     keyclass = (*env)->FindClass(env, "java/awt/event/KeyEvent");
     DASSERT (keyclass != NULL);
 
@@ -197,9 +194,6 @@
                            "Lsun/awt/AppContext;");
 
     (*env)->DeleteLocalRef(env, keyclass);
-
-    DASSERT(componentIDs.resetGCMID);
-
 }
 
 
--- a/src/windows/classes/sun/awt/Win32GraphicsDevice.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/windows/classes/sun/awt/Win32GraphicsDevice.java	Fri Feb 20 17:34:16 2009 +0300
@@ -380,7 +380,6 @@
 
             // fix for 4868278
             peer.updateGC();
-            peer.resetTargetGC();
         }
     }
 
--- a/src/windows/classes/sun/awt/windows/WCanvasPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WCanvasPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -38,44 +38,12 @@
 
     private boolean eraseBackground;
 
-    Method resetGCMethod;
-
     // Toolkit & peer internals
 
     WCanvasPeer(Component target) {
         super(target);
     }
 
-    /*
-     * From the DisplayChangedListener interface.
-     *
-     * Overrides WComponentPeer version because Canvases can be created with
-     * a non-defulat GraphicsConfiguration, which is no longer valid.
-     * Up-called for other windows peer instances (WPanelPeer, WWindowPeer).
-     */
-    public void displayChanged() {
-        clearLocalGC();
-        resetTargetGC();
-        super.displayChanged();
-    }
-
-    /*
-     * Reset the graphicsConfiguration member of our target Component.
-     * Component.resetGC() is a package-private method, so we have to call it
-     * through reflection.
-     */
-    public void resetTargetGC() {
-        ComponentAccessor.resetGC((Component)target);
-    }
-
-    /*
-     * Clears the peer's winGraphicsConfig member.
-     * Overridden by WWindowPeer, which shouldn't have a null winGraphicsConfig.
-     */
-    void clearLocalGC() {
-        winGraphicsConfig = null;
-    }
-
     native void create(WComponentPeer parent);
 
     void initialize() {
@@ -152,4 +120,10 @@
      */
     private native void setNativeBackgroundErase(boolean doErase,
                                                  boolean doEraseOnResize);
+
+    public GraphicsConfiguration getAppropriateGraphicsConfiguration(
+            GraphicsConfiguration gc)
+    {
+        return gc;
+    }
 }
--- a/src/windows/classes/sun/awt/windows/WComponentPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WComponentPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -59,7 +59,7 @@
 
 
 public abstract class WComponentPeer extends WObjectPeer
-    implements ComponentPeer, DropTargetPeer, DisplayChangedListener
+    implements ComponentPeer, DropTargetPeer
 {
     /**
      * Handle to native window
@@ -452,15 +452,8 @@
         }
     }
 
-    /**
-     * From the DisplayChangedListener interface.
-     *
-     * Called after a change in the display mode.  This event
-     * triggers replacing the surfaceData object (since that object
-     * reflects the current display depth information, which has
-     * just changed).
-     */
-    public void displayChanged() {
+    public void updateGraphicsData(GraphicsConfiguration gc) {
+        winGraphicsConfig = (Win32GraphicsConfig)gc;
         try {
             replaceSurfaceData();
         } catch (InvalidPipeException e) {
@@ -468,13 +461,6 @@
         }
     }
 
-    /**
-     * Part of the DisplayChangedListener interface: components
-     * do not need to react to this event
-     */
-    public void paletteChanged() {
-    }
-
     //This will return null for Components not yet added to a Container
     public ColorModel getColorModel() {
         GraphicsConfiguration gc = getGraphicsConfiguration();
--- a/src/windows/classes/sun/awt/windows/WPanelPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WPanelPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -100,34 +100,6 @@
         return getInsets();
     }
 
-    /*
-     * From the DisplayChangedListener interface. Often is
-     * up-called from a WWindowPeer instance.
-     */
-    public void displayChanged() {
-        super.displayChanged();
-        displayChanged((Container)target);
-    }
-
-    /*
-     * Recursively iterates through all the HW and LW children
-     * of the container and calls displayChanged() for HW peers.
-     * Iteration through children peers only is not enough as the
-     * displayChanged notification may not be propagated to HW
-     * components inside LW containers, see 4452373 for details.
-     */
-    private static void displayChanged(Container target) {
-        Component children[] = ((Container)target).getComponents();
-        for (Component child : children) {
-            ComponentPeer cpeer = child.getPeer();
-            if (cpeer instanceof WComponentPeer) {
-                ((WComponentPeer)cpeer).displayChanged();
-            } else if (child instanceof Container) {
-                displayChanged((Container)child);
-            }
-        }
-    }
-
     private native void pRestack(Object[] peers);
     private void restack(Container cont, Vector peers) {
         for (int i = 0; i < cont.getComponentCount(); i++) {
--- a/src/windows/classes/sun/awt/windows/WWindowPeer.java	Thu Feb 19 14:10:19 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WWindowPeer.java	Fri Feb 20 17:34:16 2009 +0300
@@ -41,7 +41,9 @@
 
 import sun.java2d.pipe.Region;
 
-public class WWindowPeer extends WPanelPeer implements WindowPeer {
+public class WWindowPeer extends WPanelPeer implements WindowPeer,
+       DisplayChangedListener
+{
 
     private static final Logger log = Logger.getLogger("sun.awt.windows.WWindowPeer");
     private static final Logger screenLog = Logger.getLogger("sun.awt.windows.screen.WWindowPeer");
@@ -198,7 +200,6 @@
         // super.displayChanged() in WWindowPeer.displayChanged() regardless of whether
         // GraphicsDevice was really changed, or not. So we need to track it here.
         updateGC();
-        resetTargetGC();
 
         realShow();
         updateMinimumSize();
@@ -400,14 +401,6 @@
         });
     }
 
-
-    /*
-     * Called from WCanvasPeer.displayChanged().
-     * Override to do nothing - Window and WWindowPeer GC must never be set to
-     * null!
-     */
-    void clearLocalGC() {}
-
     public void updateGC() {
         int scrn = getScreenImOn();
         if (screenLog.isLoggable(Level.FINER)) {
@@ -446,18 +439,36 @@
             oldDev.removeDisplayChangedListener(this);
             newDev.addDisplayChangedListener(this);
         }
+
+        SunToolkit.executeOnEventHandlerThread((Component)target,
+                new Runnable() {
+                    public void run() {
+                        AWTAccessor.getComponentAccessor().
+            setGraphicsConfiguration((Component)target, winGraphicsConfig);
+                    }
+                });
     }
 
-    /*
-     * From the DisplayChangedListener interface
+    /**
+     * From the DisplayChangedListener interface.
      *
      * This method handles a display change - either when the display settings
      * are changed, or when the window has been dragged onto a different
      * display.
+     * Called after a change in the display mode.  This event
+     * triggers replacing the surfaceData object (since that object
+     * reflects the current display depth information, which has
+     * just changed).
      */
     public void displayChanged() {
         updateGC();
-        super.displayChanged();
+    }
+
+    /**
+     * Part of the DisplayChangedListener interface: components
+     * do not need to react to this event
+     */
+    public void paletteChanged() {
     }
 
     private native int getScreenImOn();