JDK-6884960 : java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java fails
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2009-09-23
  • Updated: 2011-01-19
  • Resolved: 2009-11-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b77Fixed
Related Reports
Relates :  
Relates :  
Description
The fix for 6794764 breaks the test.

The test actually adds a heavyweight component (the JApplet) into a translucent frame - this is a sort of configuration that is not quite supported by our transparency machinery.

Comments
EVALUATION Apart from adding support for painting heavyweight descendants in the JComponent.paintChildren() method, the Component.getGraphics() should also be modified. Here's why: when a partial update happens (e.g., after hovering a JButton), the updated component requests a Graphics object by calling its getGraphics() method. By default this will eventually return the graphics for the nearest heavyweight ancestor of the component (i.e. the JApplet). However, we really need to do all the painting to the translucency-related graphics instead (the one returned by the Window ancestor). Therefore, the WComponentPeer.getGraphics() needs to be modified to return the correct graphics object if the component is located in a non-opaque window.
06-10-2009

SUGGESTED FIX --- old/src/share/classes/javax/swing/JComponent.java 2009-10-06 16:53:57.000000000 +0400 +++ new/src/share/classes/javax/swing/JComponent.java 2009-10-06 16:53:57.000000000 +0400 @@ -795,7 +795,6 @@ * @see java.awt.Container#paint */ protected void paintChildren(Graphics g) { - boolean isJComponent; Graphics sg = g; synchronized(getTreeLock()) { @@ -826,12 +825,22 @@ } } boolean printing = getFlag(IS_PRINTING); + final Window window = SwingUtilities.getWindowAncestor(this); + final boolean isWindowOpaque = window == null ? + true : window.isOpaque(); for (; i >= 0 ; i--) { Component comp = getComponent(i); - isJComponent = (comp instanceof JComponent); - if (comp != null && - (isJComponent || isLightweightComponent(comp)) && - (comp.isVisible() == true)) { + if (comp == null) { + continue; + } + + final boolean isJComponent = comp instanceof JComponent; + + // Enable painting of heavyweights in non-opaque windows. + // See 6884960 + if ((!isWindowOpaque || isJComponent || + isLightweightComponent(comp)) && comp.isVisible()) + { Rectangle cr; cr = comp.getBounds(tmpRect); @@ -887,6 +896,8 @@ } } } else { + // The component is either lightweight, or + // heavyweight in a non-opaque window if (!printing) { comp.paint(cg); } --- old/src/windows/classes/sun/awt/windows/WComponentPeer.java 2009-10-06 16:53:59.000000000 +0400 +++ new/src/windows/classes/sun/awt/windows/WComponentPeer.java 2009-10-06 16:53:58.000000000 +0400 @@ -551,8 +551,34 @@ final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); public Graphics getGraphics() { + if (isDisposed()) { + return null; + } + + Component target = (Component)getTarget(); + Window window = SunToolkit.getContainingWindow(target); + if (window != null && !window.isOpaque()) { + // Non-opaque windows do not support heavyweight children. + // Redirect all painting to the Window's Graphics instead. + // The caller is responsible for calling the + // WindowPeer.updateWindow() after painting has finished. + int x = 0, y = 0; + for (Component c = target; c != window; c = c.getParent()) { + x += c.getX(); + y += c.getY(); + } + + Graphics g = + ((WWindowPeer)window.getPeer()).getTranslucentGraphics(); + + g.translate(x, y); + g.clipRect(0, 0, target.getWidth(), target.getHeight()); + + return g; + } + SurfaceData surfaceData = this.surfaceData; - if (!isDisposed() && surfaceData != null) { + if (surfaceData != null) { /* Fix for bug 4746122. Color and Font shouldn't be null */ Color bgColor = background; if (bgColor == null) { --- old/src/windows/classes/sun/awt/windows/WWindowPeer.java 2009-10-06 16:54:00.000000000 +0400 +++ new/src/windows/classes/sun/awt/windows/WWindowPeer.java 2009-10-06 16:53:59.000000000 +0400 @@ -575,11 +575,17 @@ } } + public final Graphics getTranslucentGraphics() { + synchronized (getStateLock()) { + return isOpaque ? null : painter.getBackBuffer(false).getGraphics(); + } + } + @Override public Graphics getGraphics() { synchronized (getStateLock()) { if (!isOpaque) { - return painter.getBackBuffer(false).getGraphics(); + return getTranslucentGraphics(); } } return super.getGraphics();
29-09-2009

EVALUATION It isn't really feasible to support painting Canvases or AWT Applets since we can't get notified when they repaint themselves anyway. Therefore the fix should cover JApplets only.
29-09-2009

EVALUATION Note that we also may want to enforce painting of other heavyweight compoenents: like a usual Applet, or a Canvas.
25-09-2009

EVALUATION A hotfix for this bug is as follows: ************************************************* --- old/src/share/classes/javax/swing/JComponent.java 2009-09-25 18:50:24.000000000 +0400 +++ new/src/share/classes/javax/swing/JComponent.java 2009-09-25 18:50:23.000000000 +0400 @@ -830,7 +830,7 @@ Component comp = getComponent(i); isJComponent = (comp instanceof JComponent); if (comp != null && - (isJComponent || isLightweightComponent(comp)) && + (isJComponent || isLightweightComponent(comp) || comp instanceof JApplet) && (comp.isVisible() == true)) { Rectangle cr; ************************************************* In other words, we need not skip the heavyweight JApplet when painting children of a Swing component. However, this needs to be done only when the component is contained wihin a non-opaque window. In the normal opaque mode this is not needed because the JApplet paints itself in that case.
25-09-2009

EVALUATION At the first glance, it looks that we stopped invoking the Window.paintAll() (== the AWT painting), and started relying on the Swing's painting only. Since an applet is a heavyweight component, it does not get repainted by the Swing code, hence the test fails.
23-09-2009