6471693: Moving the vertical scroll bar of List in FileDialog leads Flickering in solaris
authordcherepanov
Mon, 14 Apr 2008 15:21:16 +0400
changeset 445 6f717a8cacfb
parent 444 b40ad157413b
child 446 bdcaa12a45a6
6471693: Moving the vertical scroll bar of List in FileDialog leads Flickering in solaris Summary: unite paint() calls in one call Reviewed-by: son
jdk/src/solaris/classes/sun/awt/X11/XListPeer.java
--- a/jdk/src/solaris/classes/sun/awt/X11/XListPeer.java	Sun Apr 13 23:56:20 2008 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XListPeer.java	Mon Apr 14 15:21:16 2008 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc.  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
@@ -55,14 +55,15 @@
     public final static int     DEFAULT_VISIBLE_ROWS = 4; // From java.awt.List,
     public final static int     HORIZ_SCROLL_AMT = 10;
 
-    final static int
-        PAINT_VSCROLL = 2,
-        PAINT_HSCROLL = 4,
-        PAINT_ITEMS = 8,
-        PAINT_FOCUS = 16,
-        PAINT_BACKGROUND = 32,
-        PAINT_HIDEFOCUS = 64,
-        PAINT_ALL = PAINT_VSCROLL | PAINT_HSCROLL | PAINT_ITEMS | PAINT_FOCUS | PAINT_BACKGROUND;
+    private final static int    PAINT_VSCROLL = 2;
+    private final static int    PAINT_HSCROLL = 4;
+    private final static int    PAINT_ITEMS = 8;
+    private final static int    PAINT_FOCUS = 16;
+    private final static int    PAINT_BACKGROUND = 32;
+    private final static int    PAINT_HIDEFOCUS = 64;
+    private final static int    PAINT_ALL =
+        PAINT_VSCROLL | PAINT_HSCROLL | PAINT_ITEMS | PAINT_FOCUS | PAINT_BACKGROUND;
+    private final static int    COPY_AREA = 128;
 
     XVerticalScrollbar       vsb;
     XHorizontalScrollbar     hsb;
@@ -363,35 +364,6 @@
         }
     }
 
-    Area getItemsArea(int firstItem, int lastItem) {
-        firstItem = Math.max(getFirstVisibleItem(), firstItem);
-        lastItem = Math.min(lastItem, getLastVisibleItem());
-        if (lastItem < getFirstVisibleItem()) {
-            return new Area();
-        }
-        if (firstItem <= lastItem) {
-            int startY = getItemY(firstItem);
-            int endY = getItemY(lastItem) + getItemHeight();
-            // Account for focus rectangle, instead should be called twice - before change
-            // of focusIndex and after
-            startY -= 2;
-            endY += 2;
-            // x is 0 since we need to account for focus rectangle,
-            // the same with width
-            return new Area(new Rectangle(0, startY, getItemWidth() + 3, endY-startY+1));
-        } else {
-            return new Area();
-        }
-    }
-
-    Rectangle getItemRect(int item) {
-        return new Rectangle(MARGIN, getItemY(item), getItemWidth(), getItemHeight());
-    }
-
-    Area getItemArea(int item) {
-        return new Area(getItemRect(item));
-    }
-
     public void repaintScrollbarRequest(XScrollbar scrollbar) {
         Graphics g = getGraphics();
         if (scrollbar == hsb)  {
@@ -411,14 +383,36 @@
         repaint(getFirstVisibleItem(), getLastVisibleItem(), PAINT_ALL);
     }
 
-    public void repaint(int options) {
+    private void repaint(int options) {
         repaint(getFirstVisibleItem(), getLastVisibleItem(), options);
     }
 
-    public void repaint(int firstItem, int lastItem, int options) {
+    private void repaint(int firstItem, int lastItem, int options) {
+        repaint(firstItem, lastItem, options, null, null);
+    }
+
+    /**
+     * In most cases the entire area of the component doesn't have
+     * to be repainted. The method repaints the particular areas of
+     * the component. The areas to repaint is specified by the option
+     * parameter. The possible values of the option parameter are:
+     * PAINT_VSCROLL, PAINT_HSCROLL, PAINT_ITEMS, PAINT_FOCUS,
+     * PAINT_HIDEFOCUS, PAINT_BACKGROUND, PAINT_ALL, COPY_AREA.
+     *
+     * Note that the COPY_AREA value initiates copy of a source area
+     * of the component by a distance by means of the copyArea method
+     * of the Graphics class.
+     *
+     * @param firstItem the position of the first item of the range to repaint
+     * @param lastItem the position of the last item of the range to repaint
+     * @param options specifies the particular area of the component to repaint
+     * @param source the area of the component to copy
+     * @param distance the distance to copy the source area
+     */
+    private void repaint(int firstItem, int lastItem, int options, Rectangle source, Point distance) {
         Graphics g = getGraphics();
         try {
-            painter.paint(g, firstItem, lastItem, options);
+            painter.paint(g, firstItem, lastItem, options, source, distance);
         } finally {
             g.dispose();
         }
@@ -1449,35 +1443,29 @@
         }
         vsb.setValue(vsb.getValue() + y);
 
+        Rectangle source = null;
+        Point distance = null;
+        int firstItem = 0, lastItem = 0;
+        int options = PAINT_HIDEFOCUS | PAINT_ITEMS | PAINT_VSCROLL | PAINT_FOCUS;
         if (y > 0) {
-            // Fixed 6308295: XAWTduplicate list item is displayed
-            // Window resizing leads to the buffer flushing
-            // That's why the repainting with the PAINT_HIDEFOCUS option is the repainting with PAINT_ALL option
-            // So we should do only the repainting instead of the copy area
-            if (y < itemsInWin && painter.isBuffer()) {
-                if (log.isLoggable(Level.FINEST)) {
-                    log.finest("Copying " + "" + MARGIN + "," + ( MARGIN + pixelsToScroll)
-                               + "," +  (width - SCROLLBAR_AREA) + "," +  (h * (itemsInWin - y)-1) +
-                               "," + 0 + "," + (-pixelsToScroll));
-                }
-                // Unpaint focus before copying
-                repaint(PAINT_HIDEFOCUS);
-                painter.copyArea(MARGIN, MARGIN + pixelsToScroll, width - SCROLLBAR_AREA, h * (itemsInWin - y - 1)-1, 0, -pixelsToScroll);
+            if (y < itemsInWin) {
+                source = new Rectangle(MARGIN, MARGIN + pixelsToScroll, width - SCROLLBAR_AREA, h * (itemsInWin - y - 1)-1);
+                distance = new Point(0, -pixelsToScroll);
+                options |= COPY_AREA;
             }
-            repaint(vsb.getValue() + (itemsInWin - y)-1, (vsb.getValue() + itemsInWin) - 1, PAINT_ITEMS | PAINT_VSCROLL | PAINT_FOCUS);
-        } else if (y < 0 && painter.isBuffer()) {
+            firstItem = vsb.getValue() + itemsInWin - y - 1;
+            lastItem = vsb.getValue() + itemsInWin - 1;
+
+        } else if (y < 0) {
             if (y + itemsInWindow() > 0) {
-                if (log.isLoggable(Level.FINEST)) {
-                    log.finest("Copying " + MARGIN + "," + MARGIN +"," +
-                               (width - SCROLLBAR_AREA) + "," +
-                               (h * (itemsInWin + y)) + "," + "0" +"," +(-pixelsToScroll));
-                }
-                repaint(PAINT_HIDEFOCUS);
-                painter.copyArea(MARGIN, MARGIN, width - SCROLLBAR_AREA, h * (itemsInWin + y), 0, -pixelsToScroll);
+                source = new Rectangle(MARGIN, MARGIN, width - SCROLLBAR_AREA, h * (itemsInWin + y));
+                distance = new Point(0, -pixelsToScroll);
+                options |= COPY_AREA;
             }
-            int e = Math.min(getLastVisibleItem(), vsb.getValue() + -y);
-            repaint(vsb.getValue(), e, PAINT_ITEMS | PAINT_VSCROLL | PAINT_FOCUS);
+            firstItem = vsb.getValue();
+            lastItem = Math.min(getLastVisibleItem(), vsb.getValue() + -y);
         }
+        repaint(firstItem, lastItem, options, source, distance);
     }
 
     /**
@@ -1491,12 +1479,17 @@
         int h = height - (SCROLLBAR_AREA + (2 * MARGIN));
         hsb.setValue(hsb.getValue() + x);
 
-        if (x < 0 && painter.isBuffer()) {
-            painter.copyArea(MARGIN + SPACE, MARGIN, w + x, h, -x, 0);
-        } else if (x > 0 && painter.isBuffer()) {
-            painter.copyArea(MARGIN + SPACE + x, MARGIN, w - x, h, -x, 0);
+        Rectangle source = null;
+        Point distance = null;
+        if (x < 0) {
+            source = new Rectangle(MARGIN + SPACE, MARGIN, w + x, h);
+            distance = new Point(-x, 0);
+        } else if (x > 0) {
+            source = new Rectangle(MARGIN + SPACE + x, MARGIN, w - x, h);
+            distance = new Point(-x, 0);
         }
-        repaint(vsb.getValue(), lastItemDisplayed(), PAINT_ITEMS | PAINT_HSCROLL);
+        int options = COPY_AREA | PAINT_ITEMS | PAINT_HSCROLL;
+        repaint(vsb.getValue(), lastItemDisplayed(), options, source, distance);
     }
 
     /**
@@ -1677,7 +1670,6 @@
      * Since we can't guarantee the sequence, use awtLock.
      */
     class ListPainter {
-        // TODO: use VolatileImage
         VolatileImage buffer;
         Color[] colors;
 
@@ -1746,6 +1738,11 @@
         }
 
         private void paint(Graphics listG, int firstItem, int lastItem, int options) {
+            paint(listG, firstItem, lastItem, options, null, null);
+        }
+
+        private void paint(Graphics listG, int firstItem, int lastItem, int options,
+                           Rectangle source, Point distance) {
             if (log.isLoggable(Level.FINER)) log.finer("Repaint from " + firstItem + " to " + lastItem + " options " + options);
             if (firstItem > lastItem) {
                 int t = lastItem;
@@ -1773,17 +1770,34 @@
                       invalidate();
                       options = PAINT_ALL;
                       continue;
+                  case VolatileImage.IMAGE_RESTORED:
+                      options = PAINT_ALL;
                 }
                 Graphics g = localBuffer.createGraphics();
 
+                // Note that the order of the following painting operations
+                // should not be modified
                 try {
                     g.setFont(getFont());
+
+                    // hiding the focus rectangle must be done prior to copying
+                    // area and so this is the first action to be performed
+                    if ((options & (PAINT_HIDEFOCUS)) != 0) {
+                        paintFocus(g, PAINT_HIDEFOCUS);
+                    }
+                    /*
+                     * The shift of the component contents occurs while someone
+                     * scrolls the component, the only purpose of the shift is to
+                     * increase the painting performance. The shift should be done
+                     * prior to painting any area (except hiding focus) and actually
+                     * it should never be done jointly with erase background.
+                     */
+                    if ((options & COPY_AREA) != 0) {
+                        g.copyArea(source.x, source.y, source.width, source.height,
+                            distance.x, distance.y);
+                    }
                     if ((options & PAINT_BACKGROUND) != 0) {
-                        g.setColor(SystemColor.window);
-                        g.fillRect(0, 0, width, height);
-                        g.setColor(getListBackground());
-                        g.fillRect(0, 0, listWidth, listHeight);
-                        draw3DRect(g, getSystemColors(), 0, 0, listWidth - 1, listHeight - 1, false);
+                        paintBackground(g);
                         // Since we made full erase update items
                         firstItem = getFirstVisibleItem();
                         lastItem = getLastVisibleItem();
@@ -1799,8 +1813,8 @@
                         g.setClip(getHScrollBarRec());
                         paintHorScrollbar(g, true);
                     }
-                    if ((options & (PAINT_FOCUS|PAINT_HIDEFOCUS)) != 0) {
-                        paintFocus(g, options);
+                    if ((options & (PAINT_FOCUS)) != 0) {
+                        paintFocus(g, PAINT_FOCUS);
                     }
                 } finally {
                     g.dispose();
@@ -1809,6 +1823,14 @@
             listG.drawImage(localBuffer, 0, 0, null);
         }
 
+        private void paintBackground(Graphics g) {
+            g.setColor(SystemColor.window);
+            g.fillRect(0, 0, width, height);
+            g.setColor(getListBackground());
+            g.fillRect(0, 0, listWidth, listHeight);
+            draw3DRect(g, getSystemColors(), 0, 0, listWidth - 1, listHeight - 1, false);
+        }
+
         private void paintItems(Graphics g, int firstItem, int lastItem, int options) {
             if (log.isLoggable(Level.FINER)) log.finer("Painting items from " + firstItem + " to " + lastItem + ", focused " + focusIndex + ", first " + getFirstVisibleItem() + ", last " + getLastVisibleItem());
 
@@ -1932,53 +1954,5 @@
             }
             g.setClip(clip);
         }
-
-        public void copyArea(int x, int y, int width, int height, int dx, int dy) {
-            if (log.isLoggable(Level.FINER)) log.finer("Copying area " + x + ", " + y + " " + width +
-                                                       "x" + height + ", (" + dx + "," + dy + ")");
-            VolatileImage localBuffer = null;
-            do {
-                XToolkit.awtLock();
-                try {
-                    if (createBuffer()) {
-                        // Newly created buffer should be painted over at full
-                        repaint(PAINT_ALL);
-                        return;
-                    }
-                    localBuffer = buffer;
-                } finally {
-                    XToolkit.awtUnlock();
-                }
-                switch (localBuffer.validate(getGraphicsConfiguration())) {
-                  case VolatileImage.IMAGE_INCOMPATIBLE:
-                      invalidate();
-                  case VolatileImage.IMAGE_RESTORED:
-                      // Since we've lost the content we can't just scroll - we should paint again
-                      repaint(PAINT_ALL);
-                      return;
-                }
-                Graphics g = localBuffer.createGraphics();
-                try {
-                    g.copyArea(x, y, width, height, dx, dy);
-                } finally {
-                    g.dispose();
-                }
-            } while (localBuffer.contentsLost());
-            Graphics listG = getGraphics();
-            listG.setClip(x, y, width, height);
-            listG.drawImage(localBuffer, 0, 0, null);
-            listG.dispose();
-        }
-
-        public boolean isBuffer() {
-            boolean isBuffer;
-            XToolkit.awtLock();
-            try {
-                isBuffer = (buffer != null);
-            } finally {
-                XToolkit.awtUnlock();
-            }
-            return isBuffer;
-        }
     }
 }