Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7154120

[macosx] PopupMenu Timing

    XMLWordPrintable

    Details

    • Subcomponent:
    • CPU:
      x86
    • OS:
      os_x

      Backports

        Description

        FULL PRODUCT VERSION :
        1.7.0_04-ea-b15

        ADDITIONAL OS VERSION INFORMATION :
        Mac OS X 10.7.3

        A DESCRIPTION OF THE PROBLEM :
        Before a JPopupMenu appears a screenshot of the screen area which will be covered by the popup has to be created. For this a custom PopupFactory and Popup class will be installed. The Popup#show() method is overridden to create the screenshot before the popup appears. At this point old popups are already closed. Unfortunately not on Max OSX with Java 7u4. It looks like the popus will be closed a bit later which leads to unwanted content in the screenshot - the old popup appears.
        The issue does not appear with Java 6 or on the Windows platform.

        REGRESSION. Last worked in version 6u29

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Execute the test case and open the popup menu of Menu1. By moving the mouse to Menu2 the open popup will be closed and a new popup appears.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The box with the magenta border should stay clear.
        ACTUAL -
        In the box with the magenta border parts of the popup menu (from Menu1) appear.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.awt.Color;
        import java.awt.Component;
        import java.awt.Dimension;
        import java.awt.FlowLayout;
        import java.awt.Graphics;
        import java.awt.Rectangle;
        import java.awt.Robot;
        import java.awt.image.BufferedImage;

        import javax.swing.JFrame;
        import javax.swing.JMenu;
        import javax.swing.JMenuBar;
        import javax.swing.JMenuItem;
        import javax.swing.JPanel;
        import javax.swing.SwingUtilities;
        import javax.swing.UIManager;
        import javax.swing.border.LineBorder;
        import javax.swing.plaf.metal.MetalLookAndFeel;

        public class PopupMenuHideTest extends JFrame
        {
          private static PopupMenuHideTest instance;
          private BufferedImage image;
          private JPanel panel;
          
          public static void main (String[] args) throws Exception
          {
            //JFrame.setDefaultLookAndFeelDecorated(true);
            UIManager.setLookAndFeel(new MetalLookAndFeel());
            
            SwingUtilities.invokeLater(new Runnable()
            {
              @Override
              public void run()
              {
                try
                {
                  instance = new PopupMenuHideTest();
                }
                catch (Exception e)
                {
                  e.printStackTrace();
                }
              }
            });
          }
          
          static void setBackground(BufferedImage image)
          {
            instance.image = image;
            instance.panel.revalidate();
            instance.panel.repaint();
          }
          
          public PopupMenuHideTest() throws Exception
          {
            setLayout(new FlowLayout());
            
            JMenuBar menubar = new JMenuBar();
            JMenu m1 = new JMenu("Menu 1");
            m1.add(new JMenuItem("MenuItem 1/1"));
            m1.add(new JMenuItem("MenuItem 1/2"));
            menubar.add(m1);
            
            JMenu m2 = new JMenu("Menu 2");
            m2.add(new JMenuItem("MenuItem 2/1"));
            m2.add(new JMenuItem("MenuItem 2/2"));
            menubar.add(m2);
                
            setJMenuBar(menubar);
            PopupFactory.install();

            panel = new JPanel(){
              @Override
              protected void paintComponent(Graphics g)
              {
                super.paintComponent(g);
                g.drawImage(image, 0, 0, null);
              }

              @Override
              public Dimension getPreferredSize()
              {
                return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(), image.getHeight());
              }
            };
            panel.setBorder(new LineBorder(Color.MAGENTA));
            add(panel);
            
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setTitle(getClass().getSimpleName());
            setSize(600,300);
            setLocationRelativeTo(null);
            setVisible(true);
          }
            
          
          private static class PopupFactory extends javax.swing.PopupFactory
          {
            private static PopupFactory popupFactory = new PopupFactory();
            private static javax.swing.PopupFactory storedPopupFactory;
                
            private PopupFactory()
            {
              super();
            }
                
            public static void install()
            {
              if (storedPopupFactory == null)
              {
                storedPopupFactory = getSharedInstance();
                setSharedInstance(popupFactory);
              }
            }

            public javax.swing.Popup getPopup(Component owner, Component contents, int x, int y)
            {
              javax.swing.Popup popup = super.getPopup(owner, contents, x, y);
              return new Popup(owner, contents, x, y, popup);
            }
          }
          
          
          private static class Popup extends javax.swing.Popup
          {
            private Component contents;
            private int x, y;
            private javax.swing.Popup popup;

            public Popup(Component owner, Component contents, int x, int y, javax.swing.Popup delegate)
            {
              this.contents = contents;
              this.popup = delegate;
              this.x = x;
              this.y = y;
            }
            
            public void hide()
            {
              popup.hide();
              popup = null;
            }

            public void show()
            {
              SwingUtilities.invokeLater(new Runnable()
              {
                public void run()
                {
                  createSnapshot();
                  popup.show();
                }
              });
            }

            private void createSnapshot()
            {
              try
              {
                Robot robot = new Robot();
                Dimension size = contents.getParent().getPreferredSize();
                if (size.width > 0 && size.height > 0)
                {
                  Rectangle rect = new Rectangle(x, y, size.width, size.height);
                  PopupMenuHideTest.setBackground(robot.createScreenCapture(rect));
                }
              }
              catch (Exception e)
              {
                e.printStackTrace();
              }
            }
          }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Can't find a warkaround.

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                Unassigned Unassigned
                Reporter:
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Imported:
                  Indexed: