6794764: Translucent windows are completely repainted on every paint event, on Windows
authorart
Thu, 21 May 2009 12:29:25 +0400
changeset 2808 a139a919f645
parent 2807 db01a7f6d657
child 2809 b373581f6507
6794764: Translucent windows are completely repainted on every paint event, on Windows 6719382: Printing of AWT components on windows is not working 6726866: Repainting artifacts when resizing or dragging JInternalFrames in non-opaque toplevel 6683775: Painting artifacts is seen when panel is made setOpaque(false) for a translucent window Reviewed-by: anthony, tdv, alexp
jdk/src/share/classes/java/awt/GraphicsConfiguration.java
jdk/src/share/classes/java/awt/GraphicsDevice.java
jdk/src/share/classes/java/awt/Window.java
jdk/src/share/classes/java/awt/peer/WindowPeer.java
jdk/src/share/classes/javax/swing/DefaultDesktopManager.java
jdk/src/share/classes/javax/swing/JComponent.java
jdk/src/share/classes/javax/swing/RepaintManager.java
jdk/src/share/classes/sun/awt/AWTAccessor.java
jdk/src/share/classes/sun/awt/EmbeddedFrame.java
jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java
jdk/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java
jdk/src/windows/classes/sun/awt/windows/WCanvasPeer.java
jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java
jdk/src/windows/classes/sun/awt/windows/WObjectPeer.java
jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java
jdk/src/windows/native/sun/windows/awt_Component.cpp
jdk/src/windows/native/sun/windows/awt_Component.h
jdk/src/windows/native/sun/windows/awt_Window.cpp
jdk/src/windows/native/sun/windows/awt_Window.h
jdk/test/javax/swing/JComponent/6683775/bug6683775.java
jdk/test/javax/swing/JInternalFrame/6726866/bug6726866.html
jdk/test/javax/swing/JInternalFrame/6726866/bug6726866.java
--- a/jdk/src/share/classes/java/awt/GraphicsConfiguration.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/GraphicsConfiguration.java	Thu May 21 12:29:25 2009 +0400
@@ -436,7 +436,7 @@
     }
 
     /**
-     * Returns whether this GraphicsConfiguration supports
+     * Returns whether this {@code GraphicsConfiguration} supports
      * the {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
      * PERPIXEL_TRANSLUCENT} kind of translucency.
      *
--- a/jdk/src/share/classes/java/awt/GraphicsDevice.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/GraphicsDevice.java	Thu May 21 12:29:25 2009 +0400
@@ -246,7 +246,7 @@
      * Simulated full-screen mode resizes
      * the window to the size of the screen and positions it at (0,0).
      * <p>
-     * When entering full-screen mode, if the window to be used as the
+     * When entering full-screen mode, if the window to be used as a
      * full-screen window is not visible, this method will make it visible.
      * It will remain visible when returning to windowed mode.
      * <p>
@@ -261,9 +261,9 @@
      *
      * @param w a window to use as the full-screen window; {@code null}
      * if returning to windowed mode.  Some platforms expect the
-     * fullscreen window to be a top-level component (i.e., a Frame);
-     * therefore it is preferable to use a Frame here rather than a
-     * Window.
+     * fullscreen window to be a top-level component (i.e., a {@code Frame});
+     * therefore it is preferable to use a {@code Frame} here rather than a
+     * {@code Window}.
      *
      * @see #isFullScreenSupported
      * @see #getFullScreenWindow
--- a/jdk/src/share/classes/java/awt/Window.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/Window.java	Thu May 21 12:29:25 2009 +0400
@@ -296,7 +296,7 @@
     transient boolean isInShow = false;
 
     /*
-     * Opacity level of the window
+     * The opacity level of the window
      *
      * @serial
      * @see #setOpacity(float)
@@ -306,7 +306,7 @@
     private float opacity = 1.0f;
 
     /*
-     * The shape assigned to this window. This field is set to null if
+     * The shape assigned to this window. This field is set to {@code null} if
      * no shape is set (rectangular window).
      *
      * @serial
@@ -3592,10 +3592,10 @@
     @Override
     public void setBackground(Color bgColor) {
         Color oldBg = getBackground();
+        super.setBackground(bgColor);
         if (oldBg != null && oldBg.equals(bgColor)) {
             return;
         }
-        super.setBackground(bgColor);
         int oldAlpha = oldBg != null ? oldBg.getAlpha() : 255;
         int alpha = bgColor.getAlpha();
         if ((oldAlpha == 255) && (alpha < 255)) { // non-opaque window
@@ -3623,16 +3623,37 @@
         }
     }
 
-    private void updateWindow(BufferedImage backBuffer) {
+    private void updateWindow() {
         synchronized (getTreeLock()) {
             WindowPeer peer = (WindowPeer)getPeer();
             if (peer != null) {
-                peer.updateWindow(backBuffer);
+                peer.updateWindow();
             }
         }
     }
 
-    private static final Color TRANSPARENT_BACKGROUND_COLOR = new Color(0, 0, 0, 0);
+    /**
+     * {@inheritDoc}
+     *
+     * @since 1.7
+     */
+    @Override
+    public void paint(Graphics g) {
+        Color bgColor = getBackground();
+        if ((bgColor != null) && (bgColor.getAlpha() < 255)) {
+            Graphics gg = g.create();
+            try {
+                if (gg instanceof Graphics2D) {
+                    gg.setColor(bgColor);
+                    ((Graphics2D)gg).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
+                    gg.fillRect(0, 0, getWidth(), getHeight());
+                }
+            } finally {
+                gg.dispose();
+            }
+        }
+        super.paint(g);
+    }
 
     private static void setLayersOpaque(Component component, boolean isOpaque) {
         // Shouldn't use instanceof to avoid loading Swing classes
@@ -3644,18 +3665,10 @@
             Container c = root.getContentPane();
             javax.swing.JComponent content =
                 (c instanceof javax.swing.JComponent) ? (javax.swing.JComponent)c : null;
-            javax.swing.JComponent gp =
-                (rpc.getGlassPane() instanceof javax.swing.JComponent) ?
-                (javax.swing.JComponent)rpc.getGlassPane() : null;
-            if (gp != null) {
-                gp.setDoubleBuffered(isOpaque);
-            }
             lp.setOpaque(isOpaque);
             root.setOpaque(isOpaque);
-            root.setDoubleBuffered(isOpaque);
             if (content != null) {
                 content.setOpaque(isOpaque);
-                content.setDoubleBuffered(isOpaque);
 
                 // Iterate down one level to see whether we have a JApplet
                 // (which is also a RootPaneContainer) which requires processing
@@ -3748,8 +3761,8 @@
                 window.setBackground(new Color(bg.getRed(), bg.getGreen(), bg.getBlue(),
                                                opaque ? 255 : 0));
             }
-            public void updateWindow(Window window, BufferedImage backBuffer) {
-                window.updateWindow(backBuffer);
+            public void updateWindow(Window window) {
+                window.updateWindow();
             }
 
             public Dimension getSecurityWarningSize(Window window) {
--- a/jdk/src/share/classes/java/awt/peer/WindowPeer.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/peer/WindowPeer.java	Thu May 21 12:29:25 2009 +0400
@@ -110,12 +110,11 @@
     void setOpaque(boolean isOpaque);
 
     /**
-     * Updates the native part of non-opaque window using
-     * the given image with color+alpha values for each pixel.
+     * Updates the native part of non-opaque window.
      *
      * @see Window#setBackground(Color)
      */
-    void updateWindow(BufferedImage backBuffer);
+    void updateWindow();
 
     /**
      * Instructs the peer to update the position of the security warning.
--- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java	Thu May 21 12:29:25 2009 +0400
@@ -34,6 +34,9 @@
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 
+import sun.awt.AWTAccessor;
+import sun.awt.SunToolkit;
+
 /** This is an implementation of the <code>DesktopManager</code>.
   * It currently implements the basic behaviors for managing
   * <code>JInternalFrame</code>s in an arbitrary parent.
@@ -361,7 +364,7 @@
               g.dispose();
             }
         } else if (dragMode == FASTER_DRAG_MODE) {
-          dragFrameFaster(f, newX, newY);
+            dragFrameFaster(f, newX, newY);
         } else {
             setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight());
         }
@@ -634,13 +637,8 @@
 
       boolean floaterCollision = isFloaterCollision(previousBounds, currentBounds);
 
-    // System.out.println(previousBounds);
       JComponent parent = (JComponent)f.getParent();
       Rectangle visBounds = previousBounds.intersection(desktopBounds);
-    //  System.out.println(previousBounds);
-
-
-     // System.out.println(visBounds);
 
       RepaintManager currentManager = RepaintManager.currentManager(f);
 
@@ -682,7 +680,6 @@
           } else {
               dirtyRects = new Rectangle[1];
               dirtyRects[0] = previousBounds;
-              //  System.out.println("no intersection");
           };
 
           // Fix the damage
@@ -701,14 +698,22 @@
 
                   parent.paintImmediately(dirtyRects[i]);
                   ((JInternalFrame)f).isDragging = true;
-
-                  // System.out.println(dirtyRects[i]);
               }
 
           }
       } finally {
           currentManager.endPaint();
       }
+
+      // update window if it's non-opaque
+      Window topLevel = SwingUtilities.getWindowAncestor(f);
+      Toolkit tk = Toolkit.getDefaultToolkit();
+      if (!AWTAccessor.getWindowAccessor().isOpaque(topLevel) &&
+          (tk instanceof SunToolkit) &&
+          ((SunToolkit)tk).needUpdateWindow())
+      {
+          AWTAccessor.getWindowAccessor().updateWindow(topLevel);
+      }
    }
 
    private boolean isFloaterCollision(Rectangle moveFrom, Rectangle moveTo) {
--- a/jdk/src/share/classes/javax/swing/JComponent.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/javax/swing/JComponent.java	Thu May 21 12:29:25 2009 +0400
@@ -1021,8 +1021,10 @@
 
             int bw,bh;
             boolean printing = getFlag(IS_PRINTING);
-            if(!printing && repaintManager.isDoubleBufferingEnabled() &&
-               !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) {
+            if (!printing && repaintManager.isDoubleBufferingEnabled() &&
+                !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() &&
+                (getFlag(IS_REPAINTING) || repaintManager.isPainting()))
+            {
                 repaintManager.beginPaint();
                 try {
                     repaintManager.paint(this, this, co, clipX, clipY, clipW,
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java	Thu May 21 12:29:25 2009 +0400
@@ -43,7 +43,6 @@
 
 import com.sun.java.swing.SwingUtilities3;
 
-
 /**
  * This class manages repaint requests, allowing the number
  * of repaints to be minimized, for example by collapsing multiple
@@ -717,14 +716,12 @@
         }
     }
 
-    private Map<Component,Rectangle>
-        updateWindows(Map<Component,Rectangle> dirtyComponents)
-    {
+    private void updateWindows(Map<Component,Rectangle> dirtyComponents) {
         Toolkit toolkit = Toolkit.getDefaultToolkit();
         if (!(toolkit instanceof SunToolkit &&
               ((SunToolkit)toolkit).needUpdateWindow()))
         {
-            return dirtyComponents;
+            return;
         }
 
         Set<Window> windows = new HashSet<Window>();
@@ -734,25 +731,20 @@
             Window window = dirty instanceof Window ?
                 (Window)dirty :
                 SwingUtilities.getWindowAncestor(dirty);
-
             if (window != null &&
                 !AWTAccessor.getWindowAccessor().isOpaque(window))
             {
-                // if this component's toplevel is perpixel translucent, it will
-                // be repainted below
-                it.remove();
-                // add to the set of windows to update (so that we don't update
-                // the window many times for each component to be repainted that
-                // belongs to this window)
                 windows.add(window);
             }
         }
 
         for (Window window : windows) {
-            AWTAccessor.getWindowAccessor().updateWindow(window, null);
+            AWTAccessor.getWindowAccessor().updateWindow(window);
         }
+    }
 
-        return dirtyComponents;
+    boolean isPainting() {
+        return painting;
     }
 
     /**
@@ -788,10 +780,6 @@
         int localBoundsW;
         Enumeration keys;
 
-        // the components belonging to perpixel-translucent windows will be
-        // removed from the list
-        tmpDirtyComponents = updateWindows(tmpDirtyComponents);
-
         roots = new ArrayList<Component>(count);
 
         for (Component dirty : tmpDirtyComponents.keySet()) {
@@ -799,13 +787,11 @@
         }
 
         count = roots.size();
-        //        System.out.println("roots size is " + count);
         painting = true;
         try {
             for(i=0 ; i < count ; i++) {
                 dirtyComponent = roots.get(i);
                 rect = tmpDirtyComponents.get(dirtyComponent);
-                //            System.out.println("Should refresh :" + rect);
                 localBoundsH = dirtyComponent.getHeight();
                 localBoundsW = dirtyComponent.getWidth();
 
@@ -848,6 +834,9 @@
         } finally {
             painting = false;
         }
+
+        updateWindows(tmpDirtyComponents);
+
         tmpDirtyComponents.clear();
     }
 
@@ -1004,6 +993,16 @@
             return delegate.getVolatileOffscreenBuffer(c, proposedWidth,
                                                         proposedHeight);
         }
+
+        // If the window is non-opaque, it's double-buffered at peer's level
+        Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
+        if (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
+            Toolkit tk = Toolkit.getDefaultToolkit();
+            if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
+                return null;
+            }
+        }
+
         GraphicsConfiguration config = c.getGraphicsConfiguration();
         if (config == null) {
             config = GraphicsEnvironment.getLocalGraphicsEnvironment().
@@ -1031,6 +1030,15 @@
         DoubleBufferInfo doubleBuffer;
         int width, height;
 
+        // If the window is non-opaque, it's double-buffered at peer's level
+        Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
+        if (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
+            Toolkit tk = Toolkit.getDefaultToolkit();
+            if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
+                return null;
+            }
+        }
+
         if (standardDoubleBuffer == null) {
             standardDoubleBuffer = new DoubleBufferInfo();
         }
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java	Thu May 21 12:29:25 2009 +0400
@@ -132,7 +132,7 @@
         /*
          * Update the image of a non-opaque (translucent) window.
          */
-        void updateWindow(Window window, BufferedImage backBuffer);
+        void updateWindow(Window window);
 
         /** Get the size of the security warning.
          */
--- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java	Thu May 21 12:29:25 2009 +0400
@@ -592,8 +592,9 @@
         public void setOpaque(boolean isOpaque) {
         }
 
-        public void updateWindow(BufferedImage bi) {
+        public void updateWindow() {
         }
+
         public void repositionSecurityWarning() {
         }
      }
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Thu May 21 12:29:25 2009 +0400
@@ -2058,7 +2058,7 @@
     }
 
     @Override
-    public void updateWindow(BufferedImage backBuffer) {
+    public void updateWindow() {
         // no-op
     }
 }
--- a/jdk/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java	Thu May 21 12:29:25 2009 +0400
@@ -105,9 +105,10 @@
     }
 
     /**
-     * Creates (if needed), clears and returns the buffer for this painter.
+     * Creates (if needed), clears (if requested) and returns the buffer
+     * for this painter.
      */
-    protected abstract Image getBackBuffer();
+    protected abstract Image getBackBuffer(boolean clear);
 
     /**
      * Updates the the window associated with this painter with the contents
@@ -123,31 +124,16 @@
     public abstract void flush();
 
     /**
-     * Updates the window associated with the painter given the passed image.
-     * If the passed image is null the painter will use its own buffer for
-     * rendering the contents of the window into it and updating the window.
+     * Updates the window associated with the painter.
      *
-     * If the passed buffer has dimensions different from the window, it is
-     * copied into the internal buffer first and the latter is used to update
-     * the window.
-     *
-     * @param bb the image to update the non opaque window with, or null.
-     * If not null, the image must be of ARGB_PRE type.
+     * @param repaint indicates if the window should be completely repainted
+     * to the back buffer using {@link java.awt.Window#paintAll} before update.
      */
-    public void updateWindow(Image bb) {
+    public void updateWindow(boolean repaint) {
         boolean done = false;
-        if (bb != null && (window.getWidth()  != bb.getWidth(null) ||
-                           window.getHeight() != bb.getHeight(null)))
-        {
-            Image ourBB = getBackBuffer();
-            Graphics2D g = (Graphics2D)ourBB.getGraphics();
-            g.drawImage(bb, 0, 0, null);
-            g.dispose();
-            bb = ourBB;
-        }
-        do {
-            if (bb == null) {
-                bb = getBackBuffer();
+        Image bb = getBackBuffer(repaint);
+        while (!done) {
+            if (repaint) {
                 Graphics2D g = (Graphics2D)bb.getGraphics();
                 try {
                     window.paintAll(g);
@@ -156,17 +142,12 @@
                 }
             }
 
-            peer.paintAppletWarning((Graphics2D)bb.getGraphics(),
-                                    bb.getWidth(null), bb.getHeight(null));
-
             done = update(bb);
-            // in case they passed us a lost VI, next time around we'll use our
-            // own bb because we can not validate and restore the contents of
-            // their VI
             if (!done) {
-                bb = null;
+                repaint = true;
+                bb = getBackBuffer(true);
             }
-        } while (!done);
+        }
     }
 
     private static final Image clearImage(Image bb) {
@@ -190,30 +171,24 @@
      * method (VI, BI, regular Images).
      */
     private static class BIWindowPainter extends TranslucentWindowPainter {
-        private WeakReference<BufferedImage> biRef;
+        private BufferedImage backBuffer;
 
         protected BIWindowPainter(WWindowPeer peer) {
             super(peer);
         }
 
-        private BufferedImage getBIBackBuffer() {
+        @Override
+        protected Image getBackBuffer(boolean clear) {
             int w = window.getWidth();
             int h = window.getHeight();
-            BufferedImage bb = biRef == null ? null : biRef.get();
-            if (bb == null || bb.getWidth() != w || bb.getHeight() != h) {
-                if (bb != null) {
-                    bb.flush();
-                    bb = null;
-                }
-                bb = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
-                biRef = new WeakReference<BufferedImage>(bb);
+            if (backBuffer == null ||
+                backBuffer.getWidth() != w ||
+                backBuffer.getHeight() != h)
+            {
+                flush();
+                backBuffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
             }
-            return (BufferedImage)clearImage(bb);
-        }
-
-        @Override
-        protected Image getBackBuffer() {
-            return getBIBackBuffer();
+            return clear ? (BufferedImage)clearImage(backBuffer) : backBuffer;
         }
 
         @Override
@@ -246,10 +221,7 @@
             }
 
             // copy the passed image into our own buffer, then upload
-            BufferedImage bi = getBIBackBuffer();
-            Graphics2D g = (Graphics2D)bi.getGraphics();
-            g.setComposite(AlphaComposite.Src);
-            g.drawImage(bb, 0, 0, null);
+            BufferedImage bi = (BufferedImage)clearImage(backBuffer);
 
             int data[] =
                 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
@@ -259,8 +231,9 @@
         }
 
         public void flush() {
-            if (biRef != null) {
-                biRef.clear();
+            if (backBuffer != null) {
+                backBuffer.flush();
+                backBuffer = null;
             }
         }
     }
@@ -271,27 +244,22 @@
      * Java heap-based buffer (which is then uploaded to the layered window)
      */
     private static class VIWindowPainter extends BIWindowPainter {
-        private WeakReference<VolatileImage> viRef;
+        private VolatileImage viBB;
 
         protected VIWindowPainter(WWindowPeer peer) {
             super(peer);
         }
 
         @Override
-        protected Image getBackBuffer() {
+        protected Image getBackBuffer(boolean clear) {
             int w = window.getWidth();
             int h = window.getHeight();
             GraphicsConfiguration gc = peer.getGraphicsConfiguration();
 
-            VolatileImage viBB = viRef == null ? null : viRef.get();
-
             if (viBB == null || viBB.getWidth() != w || viBB.getHeight() != h ||
                 viBB.validate(gc) == IMAGE_INCOMPATIBLE)
             {
-                if (viBB != null) {
-                    viBB.flush();
-                    viBB = null;
-                }
+                flush();
 
                 if (gc instanceof AccelGraphicsConfig) {
                     AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc);
@@ -303,21 +271,16 @@
                     viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT);
                 }
                 viBB.validate(gc);
-                viRef = new WeakReference<VolatileImage>(viBB);
             }
 
-            return clearImage(viBB);
+            return clear ? clearImage(viBB) : viBB;
         }
 
         @Override
         public void flush() {
-            if (viRef != null) {
-                VolatileImage viBB = viRef.get();
-                if (viBB != null) {
-                    viBB.flush();
-                    viBB = null;
-                }
-                viRef.clear();
+            if (viBB != null) {
+                viBB.flush();
+                viBB = null;
             }
         }
     }
--- a/jdk/src/windows/classes/sun/awt/windows/WCanvasPeer.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WCanvasPeer.java	Thu May 21 12:29:25 2009 +0400
@@ -78,25 +78,6 @@
         super.paint(g);
     }
 
-    public void print(Graphics g) {
-        if (!(target instanceof Window) ||
-            AWTAccessor.getWindowAccessor().isOpaque((Window)target))
-        {
-            Dimension d = ((Component)target).getSize();
-            if (g instanceof Graphics2D ||
-                g instanceof sun.awt.Graphics2Delegate) {
-                // background color is setup correctly, so just use clearRect
-                g.clearRect(0, 0, d.width, d.height);
-            } else {
-                // emulate clearRect
-                g.setColor(((Component)target).getBackground());
-                g.fillRect(0, 0, d.width, d.height);
-                g.setColor(((Component)target).getForeground());
-            }
-        }
-        super.print(g);
-    }
-
     public boolean shouldClearRectBeforePaint() {
         return eraseBackground;
     }
--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java	Thu May 21 12:29:25 2009 +0400
@@ -239,7 +239,8 @@
 
     private static final double BANDING_DIVISOR = 4.0;
     private native int[] createPrintedPixels(int srcX, int srcY,
-                                             int srcW, int srcH);
+                                             int srcW, int srcH,
+                                             int alpha);
     public void print(Graphics g) {
 
         Component comp = (Component)target;
@@ -261,7 +262,9 @@
             }
             int h = endY - startY + 1;
 
-            int[] pix = createPrintedPixels(0, startY, totalW, h);
+            Color bgColor = comp.getBackground();
+            int[] pix = createPrintedPixels(0, startY, totalW, h,
+                                            bgColor == null ? 255 : bgColor.getAlpha());
             if (pix != null) {
                 BufferedImage bim = new BufferedImage(totalW, h,
                                               BufferedImage.TYPE_INT_ARGB);
--- a/jdk/src/windows/classes/sun/awt/windows/WObjectPeer.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WObjectPeer.java	Thu May 21 12:29:25 2009 +0400
@@ -42,6 +42,9 @@
     // set from JNI if any errors in creating the peer occur
     protected Error createError = null;
 
+    // used to synchronize the state of this peer
+    private final Object stateLock = new Object();
+
     public static WObjectPeer getPeerForTarget(Object t) {
         WObjectPeer peer = (WObjectPeer) WToolkit.targetToPeer(t);
         return peer;
@@ -55,6 +58,10 @@
         return target;
     }
 
+    public final Object getStateLock() {
+        return stateLock;
+    }
+
     /*
      * Subclasses should override disposeImpl() instead of dispose(). Client
      * code should always invoke dispose(), never disposeImpl().
--- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Thu May 21 12:29:25 2009 +0400
@@ -54,7 +54,7 @@
 
     private boolean isOpaque;
 
-    private volatile TranslucentWindowPainter painter;
+    private TranslucentWindowPainter painter;
 
     /*
      * A key used for storing a list of active windows in AppContext. The value
@@ -106,11 +106,13 @@
         GraphicsConfiguration gc = getGraphicsConfiguration();
         ((Win32GraphicsDevice)gc.getDevice()).removeDisplayChangedListener(this);
 
-        TranslucentWindowPainter currentPainter = painter;
-        if (currentPainter != null) {
-            currentPainter.flush();
-            // don't set the current one to null here; reduces the chances of
-            // MT issues (like NPEs)
+        synchronized (getStateLock()) {
+            TranslucentWindowPainter currentPainter = painter;
+            if (currentPainter != null) {
+                currentPainter.flush();
+                // don't set the current one to null here; reduces the chances of
+                // MT issues (like NPEs)
+            }
         }
 
         super.disposeImpl();
@@ -178,9 +180,23 @@
 
         updateIconImages();
 
-        updateShape();
-        updateOpacity();
-        updateOpaque();
+        Shape shape = ((Window)target).getShape();
+        if (shape != null) {
+            applyShape(Region.getInstance(shape, null));
+        }
+
+        float opacity = ((Window)target).getOpacity();
+        if (opacity < 1.0f) {
+            setOpacity(opacity);
+        }
+
+        synchronized (getStateLock()) {
+            // default value of a boolean field is 'false', so set isOpaque to
+            // true here explicitly
+            this.isOpaque = true;
+            Color bgColor = ((Window)target).getBackground();
+            setOpaque((bgColor == null) || (bgColor.getAlpha() == 255));
+        }
     }
 
     native void createAwtWindow(WComponentPeer parent);
@@ -214,7 +230,11 @@
             setAlwaysOnTop(alwaysOnTop);
         }
 
-        updateWindow(null);
+        synchronized (getStateLock()) {
+            if (!isOpaque) {
+                updateWindow(true);
+            }
+        }
     }
 
     // Synchronize the insets members (here & in helper) with actual window
@@ -334,29 +354,6 @@
         }
     }
 
-    private void updateShape() {
-        Shape shape = ((Window)target).getShape();
-        if (shape != null) {
-            applyShape(Region.getInstance(shape, null));
-        }
-    }
-
-    private void updateOpacity() {
-        float opacity = ((Window)target).getOpacity();
-        if (opacity < 1.0f) {
-            setOpacity(opacity);
-        }
-    }
-
-    private void updateOpaque() {
-        this.isOpaque = true;
-        // boolean opaque = ((Window)target).isOpaque();
-        boolean opaque = AWTAccessor.getWindowAccessor().isOpaque((Window)target);
-        if (!opaque) {
-            setOpaque(opaque);
-        }
-    }
-
     native void setMinSize(int width, int height);
 
 /*
@@ -579,6 +576,26 @@
         }
     }
 
+    @Override
+    public Graphics getGraphics() {
+        synchronized (getStateLock()) {
+            if (!isOpaque) {
+                return painter.getBackBuffer(false).getGraphics();
+            }
+        }
+        return super.getGraphics();
+    }
+
+    @Override
+    public void setBackground(Color c) {
+        super.setBackground(c);
+        synchronized (getStateLock()) {
+            if (!isOpaque && ((Window)target).isVisible()) {
+                updateWindow(true);
+            }
+        }
+    }
+
     private native void setOpacity(int iOpacity);
 
     public void setOpacity(float opacity) {
@@ -600,12 +617,23 @@
         }
 
         setOpacity(iOpacity);
-        updateWindow(null);
+
+        synchronized (getStateLock()) {
+            if (!isOpaque && ((Window)target).isVisible()) {
+                updateWindow(true);
+            }
+        }
     }
 
     private native void setOpaqueImpl(boolean isOpaque);
 
     public void setOpaque(boolean isOpaque) {
+        synchronized (getStateLock()) {
+            if (this.isOpaque == isOpaque) {
+                return;
+            }
+        }
+
         Window target = (Window)getTarget();
 
         if (!isOpaque) {
@@ -617,20 +645,17 @@
             }
         }
 
-        boolean opaqueChanged = this.isOpaque != isOpaque;
         boolean isVistaOS = Win32GraphicsEnvironment.isVistaOS();
 
-        if (opaqueChanged && !isVistaOS){
+        if (!isVistaOS) {
             // non-Vista OS: only replace the surface data if the opacity
             // status changed (see WComponentPeer.isAccelCapable() for more)
             replaceSurfaceDataRecursively(target);
         }
 
-        this.isOpaque = isOpaque;
-
-        setOpaqueImpl(isOpaque);
-
-        if (opaqueChanged) {
+        synchronized (getStateLock()) {
+            this.isOpaque = isOpaque;
+            setOpaqueImpl(isOpaque);
             if (isOpaque) {
                 TranslucentWindowPainter currentPainter = painter;
                 if (currentPainter != null) {
@@ -642,7 +667,7 @@
             }
         }
 
-        if (opaqueChanged && isVistaOS) {
+        if (isVistaOS) {
             // On Vista: setting the window non-opaque makes the window look
             // rectangular, though still catching the mouse clicks within
             // its shape only. To restore the correct visual appearance
@@ -654,42 +679,33 @@
             }
         }
 
-        updateWindow(null);
+        if (((Window)target).isVisible()) {
+            updateWindow(true);
+        }
     }
 
     public native void updateWindowImpl(int[] data, int width, int height);
 
-    public void updateWindow(BufferedImage backBuffer) {
-        if (isOpaque) {
-            return;
-        }
-
-        Component target = (Component)this.target;
-        if (target.getWidth() <= 0 || target.getHeight() <= 0) {
-            return;
-        }
-
-        TranslucentWindowPainter currentPainter = painter;
-        if (currentPainter != null) {
-            currentPainter.updateWindow(backBuffer);
-        } else if (log.isLoggable(Level.FINER)) {
-            log.log(Level.FINER,
-                    "Translucent window painter is null in updateWindow");
-        }
+    public void updateWindow() {
+        updateWindow(false);
     }
 
-    /**
-     * Paints the Applet Warning into the passed Graphics2D. This method is
-     * called by the TranslucentWindowPainter before updating the layered
-     * window.
-     *
-     * @param g Graphics context to paint the warning to
-     * @param w the width of the area
-     * @param h the height of the area
-     * @see TranslucentWindowPainter
-     */
-    public void paintAppletWarning(Graphics2D g, int w, int h) {
-        // REMIND: the applet warning needs to be painted here
+    private void updateWindow(boolean repaint) {
+        Window w = (Window)target;
+        synchronized (getStateLock()) {
+            if (isOpaque || !w.isVisible() ||
+                (w.getWidth() <= 0) || (w.getHeight() <= 0))
+            {
+                return;
+            }
+            TranslucentWindowPainter currentPainter = painter;
+            if (currentPainter != null) {
+                currentPainter.updateWindow(repaint);
+            } else if (log.isLoggable(Level.FINER)) {
+                log.log(Level.FINER,
+                        "Translucent window painter is null in updateWindow");
+            }
+        }
     }
 
     /*
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp	Thu May 21 12:29:25 2009 +0400
@@ -30,6 +30,7 @@
 
 #include "jlong.h"
 #include "awt_AWTEvent.h"
+#include "awt_BitmapUtil.h"
 #include "awt_Component.h"
 #include "awt_Cursor.h"
 #include "awt_Dimension.h"
@@ -127,6 +128,7 @@
     jobject component;
     int srcx, srcy;
     int srcw, srch;
+    jint alpha;
 };
 // Struct for _SetRectangularShape() method
 struct SetRectangularShapeStruct {
@@ -361,8 +363,8 @@
 AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) {
     AwtComponent *component =
         (AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
-    DASSERT( !IsBadReadPtr(component, sizeof(AwtComponent)) );
-    DASSERT( component->GetHWnd() == hWnd );
+    DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) );
+    DASSERT(!component || component->GetHWnd() == hWnd );
     return component;
 }
 
@@ -1918,11 +1920,14 @@
           mr = mrConsume;
           break;
       }
-      case WM_AWT_CREATE_PRINTED_PIXELS:
-          retValue = (LRESULT)CreatePrintedPixels(*((SIZE *)wParam),
-                                                  *((SIZE *)lParam));
+      case WM_AWT_CREATE_PRINTED_PIXELS: {
+          CreatePrintedPixelsStruct* cpps = (CreatePrintedPixelsStruct*)wParam;
+          SIZE loc = { cpps->srcx, cpps->srcy };
+          SIZE size = { cpps->srcw, cpps->srch };
+          retValue = (LRESULT)CreatePrintedPixels(loc, size, cpps->alpha);
           mr = mrConsume;
           break;
+      }
       case WM_UNDOCUMENTED_CLICKMENUBAR:
       {
           if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
@@ -4526,18 +4531,20 @@
 
 void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
 {
-    if (bitmapBits) {
-        DWORD* dest = (DWORD*)bitmapBits;
-        //XXX: might be optimized to use one loop (cy*cx -> 0).
-        for (int i = 0; i < size.cy; i++ ) {
-            for (int j = 0; j < size.cx; j++ ) {
-                ((BYTE*)(dest++))[3] = alpha;
-            }
+    if (!bitmapBits) {
+        return;
+    }
+
+    DWORD* dest = (DWORD*)bitmapBits;
+    //XXX: might be optimized to use one loop (cy*cx -> 0)
+    for (int i = 0; i < size.cy; i++ ) {
+        for (int j = 0; j < size.cx; j++ ) {
+            ((BYTE*)(dest++))[3] = alpha;
         }
     }
 }
 
-jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size) {
+jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 
     if (!::IsWindowVisible(GetHWnd())) {
@@ -4549,12 +4556,12 @@
         return NULL;
     }
     HDC hMemoryDC = ::CreateCompatibleDC(hdc);
-    HBITMAP hBitmap = ::CreateCompatibleBitmap(hdc, size.cx, size.cy);
+    void *bitmapBits = NULL;
+    HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
     HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
     SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);
 
-    RECT eraseR = { 0, 0, size.cx, size.cy };
-    VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
+    FillBackground(hMemoryDC, size);
 
     VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));
 
@@ -4562,6 +4569,14 @@
     // above.
     SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);
 
+    // First make sure the system completed any drawing to the bitmap.
+    ::GdiFlush();
+
+    // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
+    // leaving it equal to zero. Hence we need to fill it manually. Otherwise
+    // the pixels will be considered transparent when interpreting the data.
+    FillAlpha(bitmapBits, size, alpha);
+
     ::SelectObject(hMemoryDC, hOldBitmap);
 
     BITMAPINFO bmi;
@@ -5937,10 +5952,6 @@
 
     CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
     jobject self = cpps->component;
-    jint srcx = cpps->srcx;
-    jint srcy = cpps->srcy;
-    jint srcw = cpps->srcw;
-    jint srch = cpps->srch;
 
     jintArray result = NULL;
     AwtComponent *c = NULL;
@@ -5950,12 +5961,7 @@
     c = (AwtComponent *)pData;
     if (::IsWindow(c->GetHWnd()))
     {
-        SIZE loc = { srcx, srcy };
-        SIZE size = { srcw, srch };
-
-        result = (jintArray)
-            c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)&loc,
-                          (LPARAM)&size);
+        result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
     }
 ret:
     env->DeleteGlobalRef(self);
@@ -6749,7 +6755,7 @@
  */
 JNIEXPORT jintArray JNICALL
 Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
-    jobject self, jint srcX, jint srcY, jint srcW, jint srcH)
+    jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
 {
     TRY;
 
@@ -6761,6 +6767,7 @@
     cpps->srcy = srcY;
     cpps->srcw = srcW;
     cpps->srch = srcH;
+    cpps->alpha = alpha;
 
     jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
         (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
--- a/jdk/src/windows/native/sun/windows/awt_Component.h	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h	Thu May 21 12:29:25 2009 +0400
@@ -596,7 +596,7 @@
 
     void UpdateColorModel();
 
-    jintArray CreatePrintedPixels(SIZE &loc, SIZE &size);
+    jintArray CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha);
 
     /*
      * HWND, AwtComponent and Java Peer interaction
@@ -738,7 +738,6 @@
     virtual void SetDragCapture(UINT flags);
     virtual void ReleaseDragCapture(UINT flags);
 
-    //These functions are overridden in AwtWindow to handle non-opaque windows.
     virtual void FillBackground(HDC hMemoryDC, SIZE &size);
     virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);
 
--- a/jdk/src/windows/native/sun/windows/awt_Window.cpp	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp	Thu May 21 12:29:25 2009 +0400
@@ -464,7 +464,7 @@
         size_t length = env->GetStringLength(javaWarningString) + 1;
         warningString = new WCHAR[length];
         env->GetStringRegion(javaWarningString, 0,
-                static_cast<jsize>(length - 1), warningString);
+                static_cast<jsize>(length - 1), reinterpret_cast<jchar*>(warningString));
         warningString[length-1] = L'\0';
 
         env->DeleteLocalRef(javaWarningString);
@@ -2651,20 +2651,6 @@
     ::LeaveCriticalSection(&contentBitmapCS);
 }
 
-void AwtWindow::FillBackground(HDC hMemoryDC, SIZE &size)
-{
-    if (isOpaque()) {
-        AwtCanvas::FillBackground(hMemoryDC, size);
-    }
-}
-
-void AwtWindow::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
-{
-    if (isOpaque()) {
-        AwtCanvas::FillAlpha(bitmapBits, size, alpha);
-    }
-}
-
 /*
  * Fixed 6353381: it's improved fix for 4792958
  * which was backed-out to avoid 5059656
--- a/jdk/src/windows/native/sun/windows/awt_Window.h	Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Window.h	Thu May 21 12:29:25 2009 +0400
@@ -343,11 +343,6 @@
     BOOL m_iconInherited;     /* TRUE if icon is inherited from the owner */
     BOOL m_filterFocusAndActivation; /* Used in the WH_CBT hook */
 
-    //These are used in AwtComponent::CreatePrintedPixels. They are overridden
-    //here to handle non-opaque windows.
-    virtual void FillBackground(HDC hMemoryDC, SIZE &size);
-    virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);
-
     inline BOOL IsUntrusted() {
         return warningString != NULL;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComponent/6683775/bug6683775.java	Thu May 21 12:29:25 2009 +0400
@@ -0,0 +1,82 @@
+/* @test
+   @bug 6683775 6794764
+   @summary Painting artifacts is seen when panel is made setOpaque(false) for a translucent window
+   @author Alexander Potochkin
+   @run main bug6683775
+*/
+
+import com.sun.awt.AWTUtilities;
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+public class bug6683775 {
+    public static void main(String[] args) throws Exception {
+        GraphicsConfiguration gc = getGC();
+        if (!AWTUtilities.isTranslucencySupported(
+                AWTUtilities.Translucency.PERPIXEL_TRANSLUCENT)
+                || gc == null) {
+            return;
+        }
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+        final JFrame testFrame = new JFrame(gc);
+
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                JFrame backgroundFrame = new JFrame("Background frame");
+                backgroundFrame.setUndecorated(true);
+                JPanel panel = new JPanel();
+                panel.setBackground(Color.RED);
+                backgroundFrame.add(panel);
+                backgroundFrame.setSize(200, 200);
+                backgroundFrame.setVisible(true);
+
+                testFrame.setUndecorated(true);
+                JPanel p = new JPanel();
+                p.setOpaque(false);
+                testFrame.add(p);
+                AWTUtilities.setWindowOpaque(testFrame, false);
+                testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+                testFrame.setSize(400, 400);
+                testFrame.setLocation(0, 0);
+                testFrame.setVisible(true);
+            }
+        });
+
+        toolkit.realSync();
+
+        //robot.getPixelColor() didn't work right for some reason
+        BufferedImage capture = robot.createScreenCapture(new Rectangle(100, 100));
+
+        int redRGB = Color.RED.getRGB();
+        if (redRGB != capture.getRGB(10, 10)) {
+            throw new RuntimeException("Transparent frame is not transparent!");
+        }
+    }
+
+    private static GraphicsConfiguration getGC() {
+        GraphicsConfiguration transparencyCapableGC =
+                GraphicsEnvironment.getLocalGraphicsEnvironment()
+                        .getDefaultScreenDevice().getDefaultConfiguration();
+        if (!AWTUtilities.isTranslucencyCapable(transparencyCapableGC)) {
+            transparencyCapableGC = null;
+
+            GraphicsEnvironment env =
+                    GraphicsEnvironment.getLocalGraphicsEnvironment();
+            GraphicsDevice[] devices = env.getScreenDevices();
+
+            for (int i = 0; i < devices.length && transparencyCapableGC == null; i++) {
+                GraphicsConfiguration[] configs = devices[i].getConfigurations();
+                for (int j = 0; j < configs.length && transparencyCapableGC == null; j++) {
+                    if (AWTUtilities.isTranslucencyCapable(configs[j])) {
+                        transparencyCapableGC = configs[j];
+                    }
+                }
+            }
+        }
+        return transparencyCapableGC;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JInternalFrame/6726866/bug6726866.html	Thu May 21 12:29:25 2009 +0400
@@ -0,0 +1,7 @@
+<html>
+<body>
+<applet  code="bug6726866.class" width=400 height=100></applet>
+Drag the internal frame inside the green undecorated window,
+if you can drag it the test passes, otherwise fails.
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JInternalFrame/6726866/bug6726866.java	Thu May 21 12:29:25 2009 +0400
@@ -0,0 +1,44 @@
+/* @test
+   @bug 6726866
+   @summary Repainting artifacts when resizing or dragging JInternalFrames in non-opaque toplevel
+   @author Alexander Potochkin
+   @run applet/manual=yesno bug6726866.html
+*/
+
+import javax.swing.*;
+import java.awt.*;
+import java.lang.reflect.Method;
+
+public class bug6726866 extends JApplet {
+
+    public void init() {
+        JFrame frame = new JFrame("bug6726866");
+        frame.setUndecorated(true);
+        setWindowNonOpaque(frame);
+
+        JDesktopPane desktop = new JDesktopPane();
+        desktop.setBackground(Color.GREEN);
+        JInternalFrame iFrame = new JInternalFrame("Test", true, true, true, true);
+        iFrame.add(new JLabel("internal Frame"));
+        iFrame.setBounds(10, 10, 300, 200);
+        iFrame.setVisible(true);
+        desktop.add(iFrame);
+        frame.add(desktop);
+
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        frame.setSize(400, 400);
+        frame.setVisible(true);
+        frame.toFront();
+    }
+
+    private void setWindowNonOpaque(Window w) {
+        try {
+            Class<?> c = Class.forName("com.sun.awt.AWTUtilities");
+            Method m = c.getMethod("setWindowOpaque", Window.class, boolean.class);
+            m.invoke(null, w, false);
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}