JDK-6670644 : non-opaque AWT frames don't get repainted once shown
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6u10
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2008-03-03
  • Updated: 2011-03-14
  • Resolved: 2008-03-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.
6u10 b20Fixed
Non-opaque AWT frames don't get their paint() method called so
there's no easy way paint after the initial show.

calling repaint() doesn't help - the paint() method doesn't
get called. Getting frame's Graphics and rendering to the window
directly doesn't work either.

Run attached test, create non-opaque frame:
  java -Dusenonop TSFrame
Or run 
  java TranslucentShapedFrameTest
and check non-opaque, create window

It is supposed to be animating (changing the colors of the gradient).

That doesn't happen. If you put a printout into the
Frame's paint() method you will see that it's not getting called.

SUGGESTED FIX --- old/src/windows/classes/sun/awt/windows/WWindowPeer.java 2008-03-06 14:40:09.000000000 +0300 +++ new/src/windows/classes/sun/awt/windows/WWindowPeer.java 2008-03-06 14:40:09.000000000 +0300 @@ -688,4 +688,12 @@ ((DataBufferInt)backBuffer.getData().getDataBuffer()).getData(), backBuffer.getWidth(), backBuffer.getHeight()); } + + public void handleEvent(AWTEvent e) { + if (!isOpaque && e.getID() == PaintEvent.UPDATE) { + updateWindow(null); + } else { + super.handleEvent(e); + } + } }

EVALUATION The reason it doesn't work is that non-opaque windows apparently don't get expose events (on XP, at least), so there are no native repaint events sent to them, ever. And there's a bug in WComponentPeer which expects a native paint event to reset "paintPending" state to false (which is set to true when the component is resized), which never happens for non-opqaue windows. So paintArea.paint() is never called, and thus paint() is never called as well. But even if it was called, it won't help because the painting code for AWT components doesn't seem to call updateWindow(). One way to force updateWindow to be called is to change the transparency of the window - then WWindowPeer.updateWindow is called - and that paints the window to a BufferedImage which is then uploaded to the window. The following hack help with this problem: ------- WComponentPeer.java ------- *** /tmp/sccs.003236 Fri Feb 29 16:52:19 2008 --- WComponentPeer.java Fri Feb 29 16:51:04 2008 *************** *** 9,14 **** --- 9,15 ---- import java.awt.*; import java.awt.peer.*; import java.awt.image.VolatileImage; + import sun.awt.AWTAccessor; import sun.awt.RepaintArea; import sun.awt.CausedFocusEvent; import sun.awt.image.SunVolatileImage; *************** *** 302,307 **** --- 303,315 ---- case PaintEvent.UPDATE: // Skip all painting while layouting and all UPDATEs // while waiting for native paint + if (target instanceof Window) { + Window w = (Window)target; + if (!AWTAccessor.getWindowAccessor().isOpaque(w)) { + ((WWindowPeer)w.getPeer()).updateWindow(null); + return; + } + } if (!isLayouting && ! paintPending) { paintArea.paint(target,shouldClearRectBeforePaint()); }