From 91debf039d373601f144583fa38e2a67716dbf64 Mon Sep 17 00:00:00 2001 From: idk Date: Fri, 25 Jul 2008 11:32:12 -0400 Subject: [PATCH] 6608456: need API to define RepaintManager per components hierarchy Reviewed-by: alexp --- make/javax/swing/Makefile | 2 +- .../com/sun/java/swing/SwingUtilities3.java | 91 ++++++++++ .../classes/javax/swing/RepaintManager.java | 51 ++++++ .../RepaintManager/6608456/bug6608456.java | 162 ++++++++++++++++++ 4 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 src/share/classes/com/sun/java/swing/SwingUtilities3.java create mode 100644 test/javax/swing/RepaintManager/6608456/bug6608456.java diff --git a/make/javax/swing/Makefile b/make/javax/swing/Makefile index c2056a45c..e112e609c 100644 --- a/make/javax/swing/Makefile +++ b/make/javax/swing/Makefile @@ -33,7 +33,7 @@ include $(BUILDDIR)/common/Defs.gmk # Files # include FILES.gmk -AUTO_FILES_JAVA_DIRS = javax/swing sun/swing +AUTO_FILES_JAVA_DIRS = javax/swing sun/swing com/sun/java/swing AUTO_JAVA_PRUNE = plaf SUBDIRS = html32dtd plaf diff --git a/src/share/classes/com/sun/java/swing/SwingUtilities3.java b/src/share/classes/com/sun/java/swing/SwingUtilities3.java new file mode 100644 index 000000000..2ace1e4ce --- /dev/null +++ b/src/share/classes/com/sun/java/swing/SwingUtilities3.java @@ -0,0 +1,91 @@ +/* + * Copyright 2002-2007 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.swing; + +import sun.awt.AppContext; +import java.awt.Component; +import javax.swing.JComponent; +import javax.swing.RepaintManager; + +/** + * A collection of utility methods for Swing. + *

+ * WARNING: While this class is public, it should not be treated as + * public API and its API may change in incompatable ways between dot dot + * releases and even patch releases. You should not rely on this class even + * existing. + * + * This is a second part of sun.swing.SwingUtilities2. It is required + * to provide services for JavaFX applets. + * + */ +public class SwingUtilities3 { + /** + * The {@code clientProperty} key for delegate {@code RepaintManager} + */ + private static final Object DELEGATE_REPAINT_MANAGER_KEY = + new StringBuilder("DelegateRepaintManagerKey"); + + /** + * Registers delegate RepaintManager for {@code JComponent}. + */ + public static void setDelegateRepaintManager(JComponent component, + RepaintManager repaintManager) { + /* setting up flag in AppContext to speed up lookups in case + * there are no delegate RepaintManagers used. + */ + AppContext.getAppContext().put(DELEGATE_REPAINT_MANAGER_KEY, + Boolean.TRUE); + + component.putClientProperty(DELEGATE_REPAINT_MANAGER_KEY, + repaintManager); + } + + /** + * Returns delegate {@code RepaintManager} for {@code component} hierarchy. + */ + public static RepaintManager getDelegateRepaintManager(Component + component) { + RepaintManager delegate = null; + if (Boolean.TRUE == AppContext.getAppContext().get( + DELEGATE_REPAINT_MANAGER_KEY)) { + while (delegate == null && component != null) { + while (component != null + && ! (component instanceof JComponent)) { + component = component.getParent(); + } + if (component != null) { + delegate = (RepaintManager) + ((JComponent) component) + .getClientProperty(DELEGATE_REPAINT_MANAGER_KEY); + component = component.getParent(); + } + + } + } + return delegate; + } +} diff --git a/src/share/classes/javax/swing/RepaintManager.java b/src/share/classes/javax/swing/RepaintManager.java index 91034dbf8..81c816022 100644 --- a/src/share/classes/javax/swing/RepaintManager.java +++ b/src/share/classes/javax/swing/RepaintManager.java @@ -40,6 +40,8 @@ import sun.awt.SunToolkit; import sun.java2d.SunGraphicsEnvironment; import sun.security.action.GetPropertyAction; +import com.sun.java.swing.SwingUtilities3; + /** * This class manages repaint requests, allowing the number @@ -303,6 +305,11 @@ public class RepaintManager */ public synchronized void addInvalidComponent(JComponent invalidComponent) { + RepaintManager delegate = getDelegate(invalidComponent); + if (delegate != null) { + delegate.addInvalidComponent(invalidComponent); + return; + } Component validateRoot = null; /* Find the first JComponent ancestor of this component whose @@ -373,6 +380,11 @@ public class RepaintManager * @see #addInvalidComponent */ public synchronized void removeInvalidComponent(JComponent component) { + RepaintManager delegate = getDelegate(component); + if (delegate != null) { + delegate.removeInvalidComponent(component); + return; + } if(invalidComponents != null) { int index = invalidComponents.indexOf(component); if(index != -1) { @@ -464,6 +476,11 @@ public class RepaintManager */ public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { + RepaintManager delegate = getDelegate(c); + if (delegate != null) { + delegate.addDirtyRegion(c, x, y, w, h); + return; + } addDirtyRegion0(c, x, y, w, h); } @@ -588,6 +605,10 @@ public class RepaintManager * dirty. */ public Rectangle getDirtyRegion(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + return delegate.getDirtyRegion(aComponent); + } Rectangle r = null; synchronized(this) { r = (Rectangle)dirtyComponents.get(aComponent); @@ -603,6 +624,11 @@ public class RepaintManager * completely painted during the next paintDirtyRegions() call. */ public void markCompletelyDirty(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + delegate.markCompletelyDirty(aComponent); + return; + } addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE); } @@ -611,6 +637,11 @@ public class RepaintManager * get painted during the next paintDirtyRegions() call. */ public void markCompletelyClean(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + delegate.markCompletelyClean(aComponent); + return; + } synchronized(this) { dirtyComponents.remove(aComponent); } @@ -623,6 +654,10 @@ public class RepaintManager * if it return true. */ public boolean isCompletelyDirty(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + return delegate.isCompletelyDirty(aComponent); + } Rectangle r; r = getDirtyRegion(aComponent); @@ -900,6 +935,10 @@ public class RepaintManager * repaint manager. */ public Image getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) { + RepaintManager delegate = getDelegate(c); + if (delegate != null) { + return delegate.getOffscreenBuffer(c, proposedWidth, proposedHeight); + } return _getOffscreenBuffer(c, proposedWidth, proposedHeight); } @@ -917,6 +956,11 @@ public class RepaintManager */ public Image getVolatileOffscreenBuffer(Component c, int proposedWidth,int proposedHeight) { + RepaintManager delegate = getDelegate(c); + if (delegate != null) { + return delegate.getVolatileOffscreenBuffer(c, proposedWidth, + proposedHeight); + } GraphicsConfiguration config = c.getGraphicsConfiguration(); if (config == null) { config = GraphicsEnvironment.getLocalGraphicsEnvironment(). @@ -1550,4 +1594,11 @@ public class RepaintManager prePaintDirtyRegions(); } } + private RepaintManager getDelegate(Component c) { + RepaintManager delegate = SwingUtilities3.getDelegateRepaintManager(c); + if (this == delegate) { + delegate = null; + } + return delegate; + } } diff --git a/test/javax/swing/RepaintManager/6608456/bug6608456.java b/test/javax/swing/RepaintManager/6608456/bug6608456.java new file mode 100644 index 000000000..1d8a14fca --- /dev/null +++ b/test/javax/swing/RepaintManager/6608456/bug6608456.java @@ -0,0 +1,162 @@ +/* + * Copyright 2007 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * + * @bug 6608456 + * @author Igor Kushnirskiy + * @summary tests if delegate RepaintManager gets invoked. + */ + +import java.awt.*; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +import javax.swing.JComponent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.RepaintManager; +import javax.swing.SwingUtilities; + + + +public class bug6608456 { + private static final TestFuture testFuture = new TestFuture(); + public static void main(String[] args) throws Exception { + final JComponent component = invokeAndWait( + new Callable() { + public JComponent call() throws Exception { + RepaintManager.setCurrentManager(new TestRepaintManager()); + JFrame frame = new JFrame("test"); + frame.setLayout(new FlowLayout()); + JButton button = new JButton("default"); + + frame.add(button); + button = new JButton("delegate"); + if ( ! registerDelegate( + button, new TestRepaintManager())) { + return null; + } + frame.add(button); + frame.pack(); + frame.setVisible(true); + return button; + } + }); + if (component == null) { + throw new RuntimeException("failed. can not register delegate"); + } + blockTillDisplayed(component); + // trigger repaint for delegate RepaintManager + invokeAndWait( + new Callable() { + public Void call() { + component.repaint(); + return null; + } + }); + try { + if (testFuture.get(10, TimeUnit.SECONDS)) { + // passed + } + } catch (Exception e) { + throw new RuntimeException("failed", e); + } finally { + JFrame frame = (JFrame) SwingUtilities + .getAncestorOfClass(JFrame.class, component); + if (frame != null) { + frame.dispose(); + } + } + } + static class TestRepaintManager extends RepaintManager { + @Override + public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { + if (RepaintManager.currentManager(c) == this) { + testFuture.defaultCalled(); + } else { + testFuture.delegateCalled(); + } + super.addDirtyRegion(c, x, y, w, h); + } + } + static class TestFuture extends FutureTask { + private volatile boolean defaultCalled = false; + private volatile boolean delegateCalled = false; + public TestFuture() { + super(new Callable() { + public Boolean call() { + return null; + } + }); + } + public void defaultCalled() { + defaultCalled = true; + updateState(); + } + public void delegateCalled() { + delegateCalled = true; + updateState(); + } + private void updateState() { + if (defaultCalled && delegateCalled) { + set(Boolean.TRUE); + } + } + } + + private static boolean registerDelegate(JComponent c, + RepaintManager repaintManager) { + boolean rv = false; + try { + Class clazz = Class.forName("com.sun.java.swing.SwingUtilities3"); + Method method = clazz.getMethod("setDelegateRepaintManager", + JComponent.class, RepaintManager.class); + method.invoke(clazz, c, repaintManager); + rv = true; + } catch (Exception ignore) { + } + return rv; + } + static T invokeAndWait(Callable callable) throws Exception { + FutureTask future = new FutureTask(callable); + SwingUtilities.invokeLater(future); + return future.get(); + } + + public static void blockTillDisplayed(Component comp) { + Point p = null; + while (p == null) { + try { + p = comp.getLocationOnScreen(); + } catch (IllegalStateException e) { + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } + } + } + } +} -- GitLab