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

On macOS (Mac OS X) getting a ScreenMenuBar when not running "com.apple.laf.AquaLookAndFeel"

XMLWordPrintable

    • b150
    • x86
    • os_x

      FULL PRODUCT VERSION :
      Java(TM) SE Runtime Environment (build 9-ea+135)

      ADDITIONAL OS VERSION INFORMATION :
       Mac OS X, 10.11.6 build: 15G1004

      A DESCRIPTION OF THE PROBLEM :
       On macOS (Mac OS X) getting a screen menu bar, when not running "com.apple.laf.AquaLookAndFeel" can only be achieved when setting the ComponentUI of a JMenuBar to an instance of com.apple.laf.AquaMenuBarUI.
      Since JDK 9 this is only possible when using "--add-exports" as a workarround.
      In contrary it is possible to instantiate javax.swing.plaf.synth.SynthMenuBarUI.
      Why not com.apple.laf.AquaMenuBarUI?

      The screen menu bar is a macOS desktop feature which is common to every macOS desktop application.
          If a desktop application does not have such a screen menu bar it will not be accepted by the user on macOS.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Set another LAF than "AquaLookAndFeel", i.e. UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
      Create a menubar in a JFrame that is a screen menu bar on macOS (-Dapple.laf.useScreenMenuBar=true)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The menu bar should appear as ScreenMenuBar on top of the display.
      ACTUAL -
      IllegalAccessError is thrown

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      "Exception in thread "AWT-EventQueue-0" java.lang.IllegalAccessError: class ScreenMenuBarLAF$ScreenJMenuBar (in unnamed module @0x3b9797b1) cannot access class com.apple.laf.AquaMenuBarUI (in module java.desktop) because module java.desktop does not export com.apple.laf to unnamed module @0x3b9797b1"

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.Toolkit;
      import java.awt.event.ActionEvent;
      import java.awt.event.KeyEvent;

      import javax.swing.AbstractAction;
      import javax.swing.JFrame;
      import javax.swing.JMenu;
      import javax.swing.JMenuBar;
      import javax.swing.JMenuItem;
      import javax.swing.JOptionPane;
      import javax.swing.KeyStroke;
      import javax.swing.UIManager;
      import javax.swing.plaf.ComponentUI;

      public class ScreenMenuBarLAF
      {
          public static class ScreenJMenuBar extends JMenuBar
          {
              ScreenJMenuBar()
              {
                  super();
              }
              
              public void updateUI()
              {
                  // use AquaMenuBarUI to get the JJMenuBar as ScreenMenuBar
                  // and not inside the JFrame
                  ComponentUI cui = new com.apple.laf.AquaMenuBarUI(); // <- IllegalAccessError
                  // ComponentUI cui = new javax.swing.plaf.synth.SynthMenuBarUI();
                  setUI(cui);
              }
          }

          private static void createAndShowGUI()
          {
              System.err.println("java.version: " + System.getProperty("java.runtime.version"));
              int shortcutKeyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
              
              JFrame frame = new JFrame("ScreenMenuBar LAF: " + UIManager.getLookAndFeel().getName());
              frame.setSize(300, 300);
              
              // create a menubar with one menu and one menu item
              JMenuBar mb = new ScreenJMenuBar();
              JMenu menu = new JMenu("Test");
              mb.add(menu);
              JMenuItem mi = new JMenuItem(new AbstractAction("A Menu Item")
              {
                  @Override
                  public void actionPerformed(ActionEvent arg0)
                  {
                      // show a message when action is fired
                      JOptionPane.showMessageDialog(null, "Menu Item selected: <" + arg0.getActionCommand()+">");
                  }
              });
              // assign a keystroke
              mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, shortcutKeyMask));
              menu.add(mi);
              frame.setJMenuBar(mb);
              
              frame.setVisible(true);
          }
          
          public static void main(String[] args)
          {
              // on macOS show menubar as ScreenMenuBar
              System.setProperty("apple.laf.useScreenMenuBar", "true");
              UIManager.getInstalledLookAndFeels(); // needed to prevent "java.lang.UnsatisfiedLinkError: com.apple.laf.ScreenMenu.addMenuListeners"
              try
              {
                  // use non "Mac OS X" LookAndFeel
                  UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
              }
              catch(Exception e)
              {
                  e.printStackTrace();
              }

              javax.swing.SwingUtilities.invokeLater(new Runnable()
              {
                  public void run()
                  {
                      createAndShowGUI();
                  }
              });
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      add "--add-exports java.desktop/com.apple.laf=ALL-UNNAMED", which is not recommended.

            azvegint Alexander Zvegintsev
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: