8033233: [JLightweightFrame] support default JViewport BLIT_SCROLL_MODE
authorant
Fri, 31 Jan 2014 18:49:58 +0400
changeset 23280 df31f522531f
parent 23279 16c1ddb7b66a
child 23281 93c0a5484bb5
8033233: [JLightweightFrame] support default JViewport BLIT_SCROLL_MODE Reviewed-by: alexsch, pchelko
jdk/src/share/classes/javax/swing/DefaultDesktopManager.java
jdk/src/share/classes/javax/swing/JViewport.java
jdk/src/share/classes/javax/swing/RepaintManager.java
jdk/src/share/classes/sun/swing/JLightweightFrame.java
jdk/src/share/classes/sun/swing/SwingAccessor.java
jdk/src/share/classes/sun/swing/SwingUtilities2.java
--- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java	Fri Jan 31 14:20:40 2014 +0400
+++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java	Fri Jan 31 18:49:58 2014 +0400
@@ -677,6 +677,11 @@
 
           f.setBounds(currentBounds);
 
+          if (!floaterCollision) {
+              Rectangle r = currentBounds;
+              currentManager.notifyRepaintPerformed(parent, r.x, r.y, r.width, r.height);
+          }
+
           if(floaterCollision) {
               // since we couldn't blit we just redraw as fast as possible
               // the isDragging mucking is to avoid activating emergency
@@ -706,6 +711,8 @@
           // Fix the damage
           for (int i = 0; i < dirtyRects.length; i++) {
               parent.paintImmediately(dirtyRects[i]);
+              Rectangle r = dirtyRects[i];
+              currentManager.notifyRepaintPerformed(parent, r.x, r.y, r.width, r.height);
           }
 
           // new areas of blit were exposed
@@ -716,9 +723,10 @@
                   dirtyRects[i].x += newX - previousBounds.x;
                   dirtyRects[i].y += newY - previousBounds.y;
                   ((JInternalFrame)f).isDragging = false;
-
                   parent.paintImmediately(dirtyRects[i]);
                   ((JInternalFrame)f).isDragging = true;
+                  Rectangle r = dirtyRects[i];
+                  currentManager.notifyRepaintPerformed(parent, r.x, r.y, r.width, r.height);
               }
 
           }
--- a/jdk/src/share/classes/javax/swing/JViewport.java	Fri Jan 31 14:20:40 2014 +0400
+++ b/jdk/src/share/classes/javax/swing/JViewport.java	Fri Jan 31 18:49:58 2014 +0400
@@ -25,8 +25,6 @@
 
 package javax.swing;
 
-import sun.swing.JLightweightFrame;
-
 import java.awt.*;
 import java.awt.event.*;
 import java.awt.peer.ComponentPeer;
@@ -37,10 +35,8 @@
 import javax.swing.border.*;
 import javax.accessibility.*;
 
-
 import java.io.Serializable;
 
-
 /**
  * The "viewport" or "porthole" through which you see the underlying
  * information. When you scroll, what moves is the viewport. It is like
@@ -364,18 +360,6 @@
         super.remove(child);
     }
 
-    @Override
-    public void addNotify() {
-        super.addNotify();
-        // JLightweightFrame does not support BLIT_SCROLL_MODE, so it should be replaced
-        Window rootWindow = SwingUtilities.getWindowAncestor(this);
-        if (rootWindow instanceof JLightweightFrame
-                && getScrollMode() == BLIT_SCROLL_MODE) {
-            setScrollMode(BACKINGSTORE_SCROLL_MODE);
-        }
-    }
-
-
     /**
      * Scrolls the view so that <code>Rectangle</code>
      * within the view becomes visible.
@@ -1109,13 +1093,15 @@
                         Graphics g = JComponent.safelyGetGraphics(this);
                         flushViewDirtyRegion(g, dirty);
                         view.setLocation(newX, newY);
-                        g.setClip(0,0,getWidth(), Math.min(getHeight(),
-                                                           jview.getHeight()));
+                        Rectangle r = new Rectangle(
+                            0, 0, getWidth(), Math.min(getHeight(), jview.getHeight()));
+                        g.setClip(r);
                         // Repaint the complete component if the blit succeeded
                         // and needsRepaintAfterBlit returns true.
                         repaintAll = (windowBlitPaint(g) &&
                                       needsRepaintAfterBlit());
                         g.dispose();
+                        rm.notifyRepaintPerformed(this, r.x, r.y, r.width, r.height);
                         rm.markCompletelyClean((JComponent)getParent());
                         rm.markCompletelyClean(this);
                         rm.markCompletelyClean(jview);
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java	Fri Jan 31 14:20:40 2014 +0400
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java	Fri Jan 31 18:49:58 2014 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,8 @@
 import sun.security.action.GetPropertyAction;
 
 import com.sun.java.swing.SwingUtilities3;
+import sun.swing.SwingAccessor;
+import sun.swing.SwingUtilities2.RepaintListener;
 
 /**
  * This class manages repaint requests, allowing the number
@@ -184,6 +186,17 @@
 
 
     static {
+        SwingAccessor.setRepaintManagerAccessor(new SwingAccessor.RepaintManagerAccessor() {
+            @Override
+            public void addRepaintListener(RepaintManager rm, RepaintListener l) {
+                rm.addRepaintListener(l);
+            }
+            @Override
+            public void removeRepaintListener(RepaintManager rm, RepaintListener l) {
+                rm.removeRepaintListener(l);
+            }
+        });
+
         volatileImageBufferEnabled = "true".equals(AccessController.
                 doPrivileged(new GetPropertyAction(
                 "swing.volatileImageBufferEnabled", "true")));
@@ -1267,6 +1280,33 @@
         getPaintManager().copyArea(c, g, x, y, w, h, deltaX, deltaY, clip);
     }
 
+    private java.util.List<RepaintListener> repaintListeners = new ArrayList<>(1);
+
+    private void addRepaintListener(RepaintListener l) {
+        repaintListeners.add(l);
+    }
+
+    private void removeRepaintListener(RepaintListener l) {
+        repaintListeners.remove(l);
+    }
+
+    /**
+     * Notify the attached repaint listeners that an area of the {@code c} component
+     * has been immediately repainted, that is without scheduling a repaint runnable,
+     * due to performing a "blit" (via calling the {@code copyArea} method).
+     *
+     * @param c the component
+     * @param x the x coordinate of the area
+     * @param y the y coordinate of the area
+     * @param w the width of the area
+     * @param h the height of the area
+     */
+    void notifyRepaintPerformed(JComponent c, int x, int y, int w, int h) {
+        for (RepaintListener l : repaintListeners) {
+            l.repaintPerformed(c, x, y, w, h);
+        }
+    }
+
     /**
      * Invoked prior to any paint/copyArea method calls.  This will
      * be followed by an invocation of <code>endPaint</code>.
--- a/jdk/src/share/classes/sun/swing/JLightweightFrame.java	Fri Jan 31 14:20:40 2014 +0400
+++ b/jdk/src/share/classes/sun/swing/JLightweightFrame.java	Fri Jan 31 18:49:58 2014 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
 import java.awt.MouseInfo;
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.awt.Window;
 import java.awt.event.ContainerEvent;
 import java.awt.event.ContainerListener;
 import java.awt.image.BufferedImage;
@@ -43,16 +44,19 @@
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.security.AccessController;
+import javax.swing.JComponent;
 
 import javax.swing.JLayeredPane;
 import javax.swing.JPanel;
 import javax.swing.JRootPane;
 import javax.swing.LayoutFocusTraversalPolicy;
+import javax.swing.RepaintManager;
 import javax.swing.RootPaneContainer;
 import javax.swing.SwingUtilities;
 
 import sun.awt.LightweightFrame;
 import sun.security.action.GetPropertyAction;
+import sun.swing.SwingUtilities2.RepaintListener;
 
 /**
  * The frame serves as a lightweight container which paints its content
@@ -89,6 +93,7 @@
     private int[] copyBuffer;
 
     private PropertyChangeListener layoutSizeListener;
+    private RepaintListener repaintListener;
 
     static {
         SwingAccessor.setJLightweightFrameAccessor(new SwingAccessor.JLightweightFrameAccessor() {
@@ -130,6 +135,30 @@
                 }
             }
         };
+
+        repaintListener = (JComponent c, int x, int y, int w, int h) -> {
+            Window jlf = SwingUtilities.getWindowAncestor(c);
+            if (jlf != JLightweightFrame.this) {
+                return;
+            }
+            Point p = SwingUtilities.convertPoint(c, x, y, jlf);
+            Rectangle r = new Rectangle(p.x, p.y, w, h).intersection(
+                    new Rectangle(0, 0, bbImage.getWidth(), bbImage.getHeight()));
+
+            if (!r.isEmpty()) {
+                notifyImageUpdated(r.x, r.y, r.width, r.height);
+            }
+        };
+
+        SwingAccessor.getRepaintManagerAccessor().addRepaintListener(
+            RepaintManager.currentManager(this), repaintListener);
+    }
+
+    @Override
+    public void dispose() {
+        SwingAccessor.getRepaintManagerAccessor().removeRepaintListener(
+            RepaintManager.currentManager(this), repaintListener);
+        super.dispose();
     }
 
     /**
@@ -209,6 +238,13 @@
         }
     }
 
+    private void notifyImageUpdated(int x, int y, int width, int height) {
+        if (copyBufferEnabled) {
+            syncCopyBuffer(false, x, y, width, height);
+        }
+        content.imageUpdated(x, y, width, height);
+    }
+
     private void initInterior() {
         contentPane = new JPanel() {
             @Override
@@ -231,10 +267,7 @@
                     EventQueue.invokeLater(new Runnable() {
                         @Override
                         public void run() {
-                            if (copyBufferEnabled) {
-                                syncCopyBuffer(false, clip.x, clip.y, clip.width, clip.height);
-                            }
-                            content.imageUpdated(clip.x, clip.y, clip.width, clip.height);
+                            notifyImageUpdated(clip.x, clip.y, clip.width, clip.height);
                         }
                     });
                 } finally {
--- a/jdk/src/share/classes/sun/swing/SwingAccessor.java	Fri Jan 31 14:20:40 2014 +0400
+++ b/jdk/src/share/classes/sun/swing/SwingAccessor.java	Fri Jan 31 18:49:58 2014 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import sun.misc.Unsafe;
 
 import java.awt.Point;
+import javax.swing.RepaintManager;
 
 import javax.swing.text.JTextComponent;
 import javax.swing.TransferHandler;
@@ -82,6 +83,14 @@
     }
 
     /**
+     * An accessor for the RepaintManager class.
+     */
+    public interface RepaintManagerAccessor {
+        void addRepaintListener(RepaintManager rm, SwingUtilities2.RepaintListener l);
+        void removeRepaintListener(RepaintManager rm, SwingUtilities2.RepaintListener l);
+    }
+
+    /**
      * The javax.swing.text.JTextComponent class accessor object.
      */
     private static JTextComponentAccessor jtextComponentAccessor;
@@ -120,6 +129,31 @@
      * Retrieve the accessor object for the JLightweightFrame class
      */
     public static JLightweightFrameAccessor getJLightweightFrameAccessor() {
+        if (jLightweightFrameAccessor == null) {
+            unsafe.ensureClassInitialized(JLightweightFrame.class);
+        }
         return jLightweightFrameAccessor;
     }
+
+    /**
+     * The RepaintManager class accessor object.
+     */
+    private static RepaintManagerAccessor repaintManagerAccessor;
+
+    /**
+     * Set an accessor object for the RepaintManager class.
+     */
+    public static void setRepaintManagerAccessor(RepaintManagerAccessor accessor) {
+        repaintManagerAccessor = accessor;
+    }
+
+    /**
+     * Retrieve the accessor object for the RepaintManager class.
+     */
+    public static RepaintManagerAccessor getRepaintManagerAccessor() {
+        if (repaintManagerAccessor == null) {
+            unsafe.ensureClassInitialized(RepaintManager.class);
+        }
+        return repaintManagerAccessor;
+    }
 }
--- a/jdk/src/share/classes/sun/swing/SwingUtilities2.java	Fri Jan 31 14:20:40 2014 +0400
+++ b/jdk/src/share/classes/sun/swing/SwingUtilities2.java	Fri Jan 31 18:49:58 2014 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1966,4 +1966,11 @@
         }
         return path;
     }
+
+    /**
+     * Used to listen to "blit" repaints in RepaintManager.
+     */
+    public interface RepaintListener {
+        void repaintPerformed(JComponent c, int x, int y, int w, int h);
+    }
 }