JDK-4295524 : Swing popup menus cause Canvas3D to flash
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.2.1,1.2.2
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: solaris_7,windows_98
  • CPU: x86,sparc
  • Submitted: 1999-11-30
  • Updated: 2000-11-06
  • Resolved: 2000-11-06
Related Reports
Relates :  
Relates :  
Description
kelvin.chung@eng 1999-12-14

Using a heavy weight component inside Swing can't eliminate
flicking when using menu, even though the heavy weight
component is double buffer.

Attach is a simple Animator program which does not use Java3D
to demostrate this problem. 

The Animator program use MyCanvas.java which is double buffered
to continuously draw a circle with changing radius. Note
that MyCanvas extends Canvas (similar to Canvas3D extends Canvas)
MyCanvas is added to JFrame. When the menu is select/travesal,
the canvas is flicking.  I already set 
        mb.setOpaque(false);
	mb.setDoubleBuffered(true);
	getRootPane().setOpaque(false);
	getRootPane().setDoubleBuffered(true);
to try my best.

It is verified that the canvas is clear() before invoke paint()
when the heavy weight component is inside swing, that's why
even though MyCanvas is double buffer it is of no use.

Please let me know if there is some API which let me
modify Animator.java (but not MyCanvas.java) 
to eliminate flicking when menu select so that we can close
this bug.



--------------------
Using swing popup menus on top of a Canvas3D causes the Canvas3D to flash.
To reproduce this:

	cd <j3d-progs>/programs/bugs/<bugid>
	java FlashBugDemo

and select any of the menu items.  It will flash about 1/2 of the time.
Here are more details.


From: "Hock, Gregg" <###@###.###>
Date: Mon, 29 Nov 1999 17:29:20 -0500

The problem has to due with a flash or flicker that occurs on a Canvas3D
whenever a JMenuBar JMenu pulldown is selected and covers the canvas.  We
believe the canvas double buffering is fine but not in combination with the
Swing JMenuBar component.  We have tried the following demo on a variety of
SUN workstations and jdk revs (1.2.1_02,04, 1.2.2, 1.3beta) and Java3D
(1.1.2) with the same flashing result.  The demo consists of Jframe with a
JMenuBar and a Canvas3D.  The contents of the canvas are taken directly from
the SUN Java3D demo HelloUniverse.  You can see the bug by traversing the
menubar and alternately making selections from the pulldowns.


From: "Hock, Gregg" <###@###.###>
Date: Tue, 30 Nov 1999 14:29:19 -0500

we compiled and tested the code on 3 machines:

1) Gateway Solo laptop running Windows 95---NO flash
    Graphics Card: Trident Cyber 9397 with 4MB memory 

2). SGI 320 running NT - NO flash
     NOTE: JmenuBar becomes yellow when using JMenu items and the Canvas3D
rotation of the cube slows dramatically.

3). DELL Power Edge 6300 Server running NT server- YES flash
     Graphics Card: ATI 3D Rage Pro
      CPU: 4x 450Mhz zeon

So in summary the runtime is not consistent on NT; however, it does exist
and we very much need a fix.




Name: tb29552			Date: 01/18/2000


Solaris VM (build Solaris_JDK_1.2.1_02, native threads, sunwjit)

Compile and run this code... It creates a simple JFrame with a JMenuBar and a
Canvas3D.  The scenegraph in the canvas is from your java3d demo hellounivers.

import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.vecmath.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;

public class FlashBugDemo
{

public static void main(String[] args)
{

  FlashBugDemo bd = new FlashBugDemo();
  bd.init();
}

public void init()
{
 
  //Create main container
  final JFrame f = new JFrame("FlashBugDemo JFrame Window");
  f.getContentPane().setLayout(new BorderLayout());


  //Create JMenuBar
  JPopupMenu.setDefaultLightWeightPopupEnabled(false);
  JMenuBar jmb = new JMenuBar();
  JMenu jm = new JMenu("File");
  jm.add("file menu item1");
  jm.add("file menu item2");
  jm.add("file menu item3");
  jmb.add(jm);
  JMenu jm2 = new JMenu("Edit");
  jm2.add("edit menu item1");
  jm2.add("edit menu item2");
  jm2.add("edit menu item3");
  jmb.add(jm2);
  JMenu jm3 = new JMenu("Tools");
  jm3.add("tools menu item1");
  jm3.add("tools menu item2");
  jm3.add("tools menu item3");
  jmb.add(jm3);


  //Add JMenuBar to the JFrame
  f.setJMenuBar(jmb);
  
  //Create JPanel for Canvas3D component
  JPanel jp = new JPanel();
  jp.setLayout(new BorderLayout());
  GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
  Canvas3D can = new Canvas3D(config);
  //can.setBackground(Color.black);
  //Create the scene for the canvas (typical java3D)
  BranchGroup scene = createSceneGraph();
  SimpleUniverse universe = new SimpleUniverse(can);
  //Set an initial eye point...(custom code)
  universe.getViewingPlatform().setNominalViewingTransform();
  //Attach the scene
  universe.addBranchGraph(scene);
  //Add Canvas3D to the JPanel
  jp.add(BorderLayout.CENTER, can);

  //Add JPanel to the JFrame
  f.getContentPane().add(BorderLayout.CENTER, jp);

  //Finish JFrame specifications
  f.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent event) {
      f.dispose();
      System.exit(0);
    }
  });

  //f.setBounds(0,0,1000,1000);
  f.setSize(1000,1000);
  //f.pack();
  f.setVisible(true);

}
    public BranchGroup createSceneGraph() {
    // Create the root of the branch graph
    BranchGroup objRoot = new BranchGroup();

    // Create the transform group node and initialize it to the
    // identity.  Enable the TRANSFORM_WRITE capability so that
    // our behavior code can modify it at runtime.  Add it to the
    // root of the subgraph.
    TransformGroup objTrans = new TransformGroup();
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objRoot.addChild(objTrans);

    // Create a simple shape leaf node, add it to the scene graph.
    objTrans.addChild(new ColorCube(0.4));

    // Create a new Behavior object that will perform the desired
    // operation on the specified transform object and add it into
    // the scene graph.
        AxisAngle4f axisAngle = new AxisAngle4f(0.0f, 0.0f, 1.0f,
                                                -(float)Math.PI / 2.0f);
    Transform3D yAxis = new Transform3D();
    Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
                    0, 0,
                    4000, 0, 0,
                    0, 0, 0);

    RotationInterpolator rotator =
        new RotationInterpolator(rotationAlpha, objTrans, yAxis,
                     0.0f, (float) Math.PI*2.0f);
    BoundingSphere bounds =
        new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
    rotator.setSchedulingBounds(bounds);
    objTrans.addChild(rotator);

        // Have Java 3D perform optimizations on this scene graph.
        objRoot.compile();

    return objRoot;
    }


}
(Review ID: 98244)
======================================================================

Comments
EVALUATION This behavior isn't new. The test code included exhibits the same behavior on 1.2.2. I've also removed all the swing code and get the same behavior with just AWT. I've attached the new test case as Test2. A couple of notes: . It seems as though the clearing of the background is happening somewhere in the native side of things. I tried overriding various Graphics class in the core to see who was calling fillRect (clear), and couldn't find one. . The requestFocus call is triggering the painting, commenting it out causes no flicker to be seen. Give the above, a better description might be: transfering focus to lightweight component causes unavoidable flickering. As this appears to be somewhere in AWT, I'm reassigning. scott.violet@eng 2000-01-05 This is not a regression since it behaves the same in 1.2.2. I have committed the bug to Merlin. Since we will not be fixing it for Kestrel, I have downgraded it to a P4. eric.hawkes@eng 2000-01-06 Unfortunately, there is no way for us to fix this problem. In order to deliver keystrokes to lightweight components, we must set native focus to the container widget (Panel or Canvas) that contains them. However, if that container widget also contains heavyweight children capable of accepting focus, Motif will not let us set focus to that container. Therefore, in order to set native focus to that container (and thus Java focus to one of its lightweight children) we must first disable focusability on that container's heavyweight children, then set focus to the container, and finally reenable focusability for the children. This causes flash. Unfortuntately, we know of no way to avoid it. Therefore, I am closing this as "will not fix". This analysis of the cause of the flash was done by the responsible engineer, ###@###.###. hania.gajewska@Eng 2000-11-06 Actually, we may have found a way to fix this. See 4419252. eric.hawkes@eng 2001-07-26
24-08-2004