<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">I’ve been thinking about this some more, and I really didn’t like the idea of adding a new method to the Application class for each application menu thing we wanted to support. I think it is much better to add a new, final ApplicationMenu class to javafx.application.<div><br></div><div>I have also added what I think is support for GTK applications, but I cannot test this because I only have an M1 Mac Mini. Is anyone with a Linux box interested in testing this? Code is at <a href="https://github.com/dkkopp/jfx/tree/appmenu">https://github.com/dkkopp/jfx/tree/appmenu</a><br><div><br></div><div>So, here is take 2:</div><div><br></div><div>Added to ConditionalFeature:</div><div><br></div><div><div><br></div><div> /**</div><div> * Indicates whether or not an application menu exists.</div><div> *</div><div> * @since JavaFX 24.0</div><div> */</div><div> APPLICATION_MENU</div><div><br></div></div><div>And in PlatformImpl:</div><div><br></div><div><div> case APPLICATION_MENU:</div><div> return PlatformUtil.isMac() || PlatformUtil.isLinux();</div></div><div><br></div><div><br></div><div>Added to javafx.application.Application:</div><div><br></div><div><div> private ApplicationMenu applicationMenu = null;</div><div><br></div><div> /**</div><div> * Gets the ApplicationMenu for this application on platforms which support this concept.</div><div> *</div><div> * @return the ApplicationMenu</div><div> *</div><div> * @throws java.lang.UnsupportedOperationException if the current platform does not support the</div><div> * ConditionalFeature.APPLICATION_MENU feature</div><div> */</div><div> public final ApplicationMenu getApplicationMenu() {</div><div> if (!PlatformImpl.isSupported(ConditionalFeature.APPLICATION_MENU)) {</div><div> throw new UnsupportedOperationException("ConditionalFeature.APPLICATION_MENU is not"</div><div> + " supported on this platform");</div><div> }</div><div><br></div><div> synchronized (this) {</div><div> if (applicationMenu == null) {</div><div> applicationMenu = new ApplicationMenu();</div><div> }</div><div> return applicationMenu;</div><div> }</div><div> }</div><div><br></div></div><div>New class added to package javafx.application:</div><div><br></div><div><div>/**</div><div> * This class provides application menu integration for an Application on platforms which support</div><div> * this concept.</div><div> *</div><div> * @since JavaFX 24.0</div><div> *</div><div> * @author David Kopp</div><div> */</div><div>public final class ApplicationMenu {</div><div><br></div><div> /**</div><div> * Package scope constructor to create the ApplicationMenu object.</div><div> */</div><div> ApplicationMenu() {</div><div> }</div><div><br></div><div> /**</div><div> * Installs a handler to show a custom about window for your application.</div><div> * <p></div><div> * Setting the handler to null reverts it to the default behavior.</div><div> *</div><div> * @param handler the handler</div><div> */</div><div> public void setAboutHandler(Runnable handler) {</div><div> PlatformImpl.setAboutHandler(handler);</div><div> }</div><div><br></div><div> /**</div><div> * Installs a handler to show a custom settings window for your application.</div><div> * <p></div><div> * Setting the handler to null reverts it to the default behavior.</div><div> *</div><div> * @param handler the handler</div><div> */</div><div> public void setSettingsHandler(Runnable handler) {</div><div> PlatformImpl.setSettingsHandler(handler);</div><div> }</div><div>}</div></div><div><br></div><div>Added to GtkApplication:</div><div><br></div><div><div> @Override</div><div> public void setAboutHandler(Runnable handler) {</div><div> aboutHandler = handler;</div><div> rebuildGtkMenu();</div><div> }</div><div><br></div><div> @Override</div><div> public void setSettingsHandler(Runnable handler) {</div><div> settingsHandler = handler;</div><div> rebuildGtkMenu();</div><div> }</div><div><br></div><div> private void rebuildGtkMenu() {</div><div> for (int index = this.gtkMenu.getItems().size() - 1; index >= 0; index--) {</div><div> this.gtkMenu.remove(index);</div><div> }</div><div><br></div><div> if (null != aboutHandler) {</div><div> MenuItem aboutMenu = createMenuItem("About " + getName(), new MenuItem.Callback() {</div><div> @Override public void action() {</div><div> aboutHandler.run();</div><div> }</div><div> @Override public void validate() {</div><div> }</div><div> });</div><div> this.gtkMenu.add(aboutMenu);</div><div> this.gtkMenu.add(MenuItem.Separator);</div><div> }</div><div><br></div><div> if (null != settingsHandler) {</div><div> MenuItem preferencesMenu = createMenuItem("Settings...", new MenuItem.Callback() {</div><div> @Override public void action() {</div><div> settingsHandler.run();</div><div> }</div><div> @Override public void validate() {</div><div> }</div><div> }, ',', KeyEvent.MODIFIER_COMMAND);</div><div> this.gtkMenu.add(preferencesMenu);</div><div> this.gtkMenu.add(MenuItem.Separator);</div><div> }</div><div> }</div><div><br></div><div> public void installGtkMenu(MenuBar menubar) {</div><div> this.gtkMenu = createMenu("GTK");</div><div><br></div><div> rebuildGtkMenu();</div><div><br></div><div> menubar.add(this.gtkMenu);</div><div> }</div><div><br></div><div> @Override public void installDefaultMenus(MenuBar menubar) {</div><div> checkEventThread();</div><div> installGtkMenu(menubar);</div><div> }</div><div><br></div></div><div>MacApplication stays the same.</div></div></body></html>