United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6670644 non-opaque AWT frames don't get repainted once shown
JDK-6670644 : non-opaque AWT frames don't get repainted once shown

Details
Type:
Bug
Submit Date:
2008-03-03
Status:
Resolved
Updated Date:
2011-03-14
Project Name:
JDK
Resolved Date:
2008-03-25
Component:
client-libs
OS:
windows_xp
Sub-Component:
java.awt
CPU:
x86
Priority:
P2
Resolution:
Fixed
Affected Versions:
6u10
Fixed Versions:
6u10 (b20)

Related Reports

Sub Tasks

Description
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.

                                    

Comments
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());
                  }
                                     
2008-03-03
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);
+         }
+     }
 }
                                     
2008-03-06



Hardware and Software, Engineered to Work Together