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

PopupMenu not adjusting its location correctly depending on taskbar's position.

    XMLWordPrintable

Details

    • Fix Understood
    • x86
    • windows_2000

    Description

      Name: rmT116609 Date: 04/22/2004


      FULL PRODUCT VERSION :
      java version "1.4.2_03"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_03-b02)
      Java HotSpot(TM) Client VM (build 1.4.2_03-b02, mixed mode)

      java version "1.5.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
      Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows 2000 [Version 5.00.2195]

      A DESCRIPTION OF THE PROBLEM :
      In 1.4 there is a package method in JPopupMenu called adjustPopupLocationToFitScreen() which will adjust the given popup location to account the desktop bounds, taskbar and multi-monitor configuration.

      But the implementation failed to consider the screenInsets properly.
      If the taskBar is present at the top or at the left of the screen the PopupMenu still goes inside the taskBar.

      The current implementation is not adjusting the screenBounds accordingly.

      Current Implementation:
      ---------------------------------
      Point adjustPopupLocationToFitScreen(int xposition, int yposition) {
      Point p = new Point(xposition, yposition);

              if(popupPostionFixDisabled == true || GraphicsEnvironment.isHeadless())
                  return p;

              Toolkit toolkit = Toolkit.getDefaultToolkit();
              Rectangle screenBounds;
              Insets screenInsets;
              GraphicsConfiguration gc = null;
              // Try to find GraphicsConfiguration, that includes mouse
              // pointer position
              GraphicsEnvironment ge =
                  GraphicsEnvironment.getLocalGraphicsEnvironment();
              GraphicsDevice[] gd = ge.getScreenDevices();
              for(int i = 0; i < gd.length; i++) {
                  if(gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
                      GraphicsConfiguration dgc =
                          gd[i].getDefaultConfiguration();
                      if(dgc.getBounds().contains(p)) {
                          gc = dgc;
                          break;
                      }
                  }
              }

              // If not found and we have invoker, ask invoker about his gc
              if(gc == null && getInvoker() != null) {
                  gc = getInvoker().getGraphicsConfiguration();
              }

              if(gc != null) {
                  // If we have GraphicsConfiguration use it to get
                  // screen bounds and insets
                  screenInsets = toolkit.getScreenInsets(gc);
                  screenBounds = gc.getBounds();
              } else {
                  // If we don't have GraphicsConfiguration use primary screen
                  // and empty insets
                  screenInsets = new Insets(0, 0, 0, 0);
                  screenBounds = new Rectangle(toolkit.getScreenSize());
              }

              int scrWidth = screenBounds.width -
                          Math.abs(screenInsets.left+screenInsets.right);
              int scrHeight = screenBounds.height -
                          Math.abs(screenInsets.top+screenInsets.bottom);

              Dimension size;

              size = JPopupMenu.this.getPreferredSize();

              if( (p.x + size.width) > screenBounds.x + scrWidth )
                   p.x = screenBounds.x + scrWidth - size.width;

              if( (p.y + size.height) > screenBounds.y + scrHeight)
                   p.y = screenBounds.y + scrHeight - size.height;

              /* Change is made to the desired (X,Y) values, when the
                 PopupMenu is too tall OR too wide for the screen
              */
              if( p.x < screenBounds.x )
                  p.x = screenBounds.x ;
              if( p.y < screenBounds.y )
                  p.y = screenBounds.y;

              return p;
          }



      Correct implementation should be:-
      Correct Implementation:
      --------------------------------
      Point adjustPopupLocationToFitScreen(int xposition, int yposition) {
      Point p = new Point(xposition, yposition);

              if(popupPostionFixDisabled == true || GraphicsEnvironment.isHeadless())
                  return p;

              Toolkit toolkit = Toolkit.getDefaultToolkit();
              Rectangle screenBounds;
              Insets screenInsets;
              GraphicsConfiguration gc = null;
              // Try to find GraphicsConfiguration, that includes mouse
              // pointer position
              GraphicsEnvironment ge =
                  GraphicsEnvironment.getLocalGraphicsEnvironment();
              GraphicsDevice[] gd = ge.getScreenDevices();
              for(int i = 0; i < gd.length; i++) {
                  if(gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
                      GraphicsConfiguration dgc =
                          gd[i].getDefaultConfiguration();
                      if(dgc.getBounds().contains(p)) {
                          gc = dgc;
                          break;
                      }
                  }
              }

              // If not found and we have invoker, ask invoker about his gc
              if(gc == null && getInvoker() != null) {
                  gc = getInvoker().getGraphicsConfiguration();
              }

              if(gc != null) {
                  // If we have GraphicsConfiguration use it to get
                  // screen bounds and insets
                  screenInsets = toolkit.getScreenInsets(gc);
                  screenBounds = gc.getBounds();
              } else {
                  // If we don't have GraphicsConfiguration use primary screen
                  // and empty insets
                  screenInsets = new Insets(0, 0, 0, 0);
                  screenBounds = new Rectangle(toolkit.getScreenSize());
              }

              int scrWidth = screenBounds.width -
                          Math.abs(screenInsets.left+screenInsets.right);
              int scrHeight = screenBounds.height -
                          Math.abs(screenInsets.top+screenInsets.bottom);

      /********************************************************/
      /***********************Modification********************/
      screenBounds.x += screenInsets.left;
      screenBounds.y += screenInsets.top;
      /********************************************************/
      /***********************Modification********************/

              Dimension size;

              size = JPopupMenu.this.getPreferredSize();

              if( (p.x + size.width) > screenBounds.x + scrWidth )
                   p.x = screenBounds.x + scrWidth - size.width;

              if( (p.y + size.height) > screenBounds.y + scrHeight)
                   p.y = screenBounds.y + scrHeight - size.height;

              /* Change is made to the desired (X,Y) values, when the
                 PopupMenu is too tall OR too wide for the screen
              */
              if( p.x < screenBounds.x )
                  p.x = screenBounds.x ;
              if( p.y < screenBounds.y )
                  p.y = screenBounds.y;

              return p;
          }


      I tested with latest JDK's 1.4.1 and 1.4.2.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Place the taskBar at the top or at the left and show any Javax.swing.JPopupMenu (run the given testcase) whose size is greater than the screen. You will notice that some portion of the PopupMenu still hides inside the taskbar.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The PopupMenu shouldn't hide inside the taskbar. It should be positioned below the taskBar.
      ACTUAL -
      The PopupMenu goes inside the taskbar.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;

      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JMenuItem;
      import javax.swing.JPanel;
      import javax.swing.JPopupMenu;

      public class TabPaneTest extends JPanel
      {
        public TabPaneTest()
        {
          final JButton popButton = new JButton("Show PopupMenu");
          this.add(popButton);

          final JPopupMenu pop = new JPopupMenu("Hai");
          for (int i = 0; i < 50; i++)
          {
            pop.add(new JMenuItem(new String("Item"+(i+1))));
          }

          popButton.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent ae)
            {
              pop.show(popButton, 0, 0);
            }
          });
        }

        public static void main(String[] args)
        {
          JFrame fr = new JFrame("TabPaneTest");
          fr.getContentPane().add(new TabPaneTest());
          fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          fr.pack();
          fr.setVisible(true);
        }

        private JPopupMenu _pop;
      }
      ---------- END SOURCE ----------
      (Incident Review ID: 230658)
      ======================================================================

      Attachments

        Activity

          People

            Unassigned Unassigned
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Imported:
              Indexed: