Provide Quit handler for system menu bar

John Hendrikx john.hendrikx at gmail.com
Tue Sep 20 09:54:53 UTC 2022


What about Alt + F4 and Ctrl + F4 on Windows?  Alt + F4 closes the 
application (which works with JavaFX already) and Ctrl + F4 is supposed 
to close a single window, but that doesn't work for JavaFX.

Also very much in favor of Keeping the API platform neutral, that's just 
how Java has worked since its inception.

--John

On 20/09/2022 06:25, Scott Palmer wrote:
> Windows applications often have an “Exit” menu item, but since it 
> isn’t standardized like it is on macOS, calling a quit handler for it 
> would need to be a manual step - but the exact same method for the 
> quit handler could be called, leaving it up to the programmer to 
> continue or not with the application exit depending on the return 
> value. This manual coding isn’t a big deal since you would also need 
> to have some app-specific handling to avoid making an Exit menu item 
> on macOS, where it would look out of place.
>
> You could add a standard “requestExit()” method to Platform that you 
> could manually bind to an Exit menu item on Windows or Linux, but it 
> would be automatically called via an internal macOS Quit handler 
> implementation.  The implementation of Platform.requestExit() on *all* 
> platforms would call a boolean method if one was registered and then 
> conditionally call Platform.exit() depending on the return value, the 
> default being to always exit if nothing was registered. On macOS it 
> would pass on the value to veto the native Quit handler as needed. I 
> haven’t checked, does Application.stop() get called on macOS if you 
> exit via the Quit menu or Command-Q? If it doesn’t, that’s another 
> benefit.  This idea should probably be opt-in via some API or system 
> property, I suppose it would have to be if it changes behaviour of 
> having Application.stop() called in some circumstances. Or you can 
> just make the setting of the handler function the “opt-in”.
>
> Btw, this reminds me of the long-standing request for system tray 
> support, along with with various other features that have equivalents 
> across multiple OS’, like showing progress on the dock icon, or a 
> numbered badge (for notifications, or unread msgs, etc).  I think 
> there are already issues in Jira for these, maybe just as a general 
> request to support some features that AWT/Swing has that JFX is still 
> missing. Most of these features are available on both Mac and Windows, 
> possibly Linux.  It would be irritating to code to different APIs for 
> each if it can be avoided, so I agree with going for a 
> platform-neutral way.
>
> Cheers,
>
> Scott
>
>> On Sep 19, 2022, at 8:11 PM, Kevin Rushforth 
>> <kevin.rushforth at oracle.com> wrote:
>>
>>  I don't see us adding 100s of OS-specific API calls, but even if we 
>> did, going down the path of exposing them as Mac APIs or Windows 
>> APIs, doesn't really seem like the direction we want to go. Whatever 
>> we do needs to balance the desire to integrate with, e.g., the macOS 
>> or Windows platform with a desire to leave the door open for it to 
>> later be implemented on the other platform(s). And the most 
>> cross-platform way to do that from an API point of view is by 
>> defining API that delivers the desired functionality in as 
>> platform-neutral a way as possible. It also needs to fit cleanly into 
>> the existing API.
>>
>> So in the specific case of a quit handler, we could define a platform 
>> API that an app could call to register a handler that gets called if 
>> the platform quit menu is selected and is able to cancel the Quit 
>> action(basically, that's what is being proposed). We could decide to 
>> provide some way for an app to query whether it is supported, but 
>> maybe we just don't need to worry about it in this specific case. We 
>> could just document that it will get called when the platform quit 
>> action is called, if there is such an action on that platform. Other 
>> than maybe mentioning in the docs that the macOS system menu "quit" 
>> action is an example of an action that would invoke this, it doesn't 
>> need to be platform-specific. One question to answer is whether we 
>> should just put this in the Platform class (where we have other 
>> similar "global" application state), the Application class (which has 
>> the life-cycle APIs), or somewhere else (which might make sense if we 
>> wanted to define an analog to the AWT Desktop class, although the 
>> existing Platform class already has some APIs like this).
>>
>> -- Kevin
>>
>>
>> On 9/19/2022 1:46 PM, Andy Goryachev wrote:
>>>
>>> Thank you, Kevin.  Your insightful feedback always pulls the 
>>> discussion in the right direction.
>>>
>>> The initial problem we are facing is access to Mac menu in general 
>>> and additional API specifically.  I can see a possibility of 
>>> extending the list of APIs that app devs would want on Mac growing, 
>>> so there should be a better way to add them.  Using hacks like 
>>> com.apple.eawt, or system properties is probably not the best 
>>> solution.  Ideally, there should be away that does not require 
>>> creative linking of stub classes on non-Mac platforms, i.e. we 
>>> should be able to use a single code base for all the platforms.
>>>
>>> ConditionalFeature might work well internally for openjfx, but I 
>>> don't think it is a good solution for actually exposing the platform 
>>> APIs to the user.
>>>
>>> So, in order to provide platform-specific API in such a way that 
>>> still allows for a single code base for multiple platform, and one 
>>> that potentially scales to tens or hundreds of API calls, I see two 
>>> solutions:
>>>
>>> 1. one start starts with a single entry point, like PlatformAPI, 
>>> described earlier.
>>>
>>> 2. a lookup-based approach, where the client code requests a 
>>> (possibly fine-grained and narrowly defined) implementation from the 
>>> system.  For example:
>>>
>>> IMacMenu impl = PlatformAPI.lookup(IMacMenu.class);
>>>
>>> (where IMacMenu is an interface that, in this example, provides 
>>> access to Mac menu, adding shutdown listeners, and so forth).
>>>
>>> if we are on windows, this method either returns null or throws an 
>>> exception, if we are on Mac, we get a working instance (a singleton 
>>> or a new instance each time, depending on the circumstances).
>>>
>>> This way we are free to extend or version the APIs without modifying 
>>> the core classes.
>>>
>>> PlatformAPI.isSupported(IMacMenu.class) might provide a way to see 
>>> whether the capability is present.
>>>
>>> The platform-specific interfaces like IMacMenu might in turn extend 
>>> some base interface that provides introspection into common 
>>> properties, such as version, description, possibly a list of other 
>>> similar capabilities that the platform supports (may be a number of 
>>> earlier versions?) and so forth.
>>>
>>> What do you think?
>>>
>>> -andy
>>>
>>> *From: *openjfx-dev <openjfx-dev-retn at openjdk.org> on behalf of 
>>> Kevin Rushforth <kevin.rushforth at oracle.com>
>>> *Date: *Monday, 2022/09/19 at 09:33
>>> *To: *openjfx-dev at openjdk.org <openjfx-dev at openjdk.org>
>>> *Subject: *Re: Provide Quit handler for system menu bar
>>>
>>> I like the idea of looking at this holistically, even if we do end 
>>> up adding such features one at a time.
>>>
>>> As for how to expose such an API, I don't much like the idea of 
>>> exposing the underlying platform explicitly unless there is no 
>>> viable alternative. A better approach is one where a feature is 
>>> optional based on whether the platform you are running on supports 
>>> that feature. Especially given, as you pointed out, that features 
>>> that are only available in one platform today might make their way 
>>> into other platforms tomorrow. As for how to let an application know 
>>> whether they can use a particular API, we already have 
>>> ConditionalFeature, so adding to that would be a reasonable thing to 
>>> consider.
>>>
>>> -- Kevin
>>>
>>> On 9/19/2022 9:06 AM, Andy Goryachev wrote:
>>>
>>>     Greetings!
>>>
>>>     Thank you for proposing a solution, Florian.  I wonder if we
>>>     should extrapolate the problem further.  Given the fact that app
>>>     developers always need access to platform specific APIs, be it
>>>     integration with Mac menu, perhaps we should consider a way to
>>>     do so in such a way that does not require various tricks.
>>>
>>>     For example, we might invent a way to query whether we are
>>>     running on a certain platform and get the corresponding APIs. 
>>>     Let's say the class is PlatformAPI:
>>>
>>>     These methods allow for querying whether the specific platform
>>>     APIs are available
>>>
>>>     PlatformAPI.isWindows();
>>>
>>>     PlatformAPI.isMacOS();
>>>
>>>     PlatformAPI.isLinux(); // isUnix()? isPosix() ?
>>>
>>>     and these will actually return a service object that provides
>>>     access to the APIs, or throws some kind of exception:
>>>
>>>     IWindowsAPI PlatformAPI.getWindowsAPI();
>>>
>>>     IMacOSAPI PlatformAPI.getMacOSAPI();
>>>
>>>     the service object returned by one of these methods might
>>>     provide further information about the platform version, as well
>>>     as access to platform-specific APIs.
>>>
>>>     Another thought is perhaps we ought to think about expanding
>>>     functionality that became available on every platform in the XXI
>>>     century (example: going to sleep/hibernate).  Possibly external
>>>     shutdown via Mac menu or a signal discussed by the OP would be
>>>     considered as platform-independent.
>>>
>>>     What do you think?
>>>
>>>     -andy
>>>
>>>     *From: *openjfx-dev <openjfx-dev-retn at openjdk.org>
>>>     <mailto:openjfx-dev-retn at openjdk.org> on behalf of Florian
>>>     Kirmaier <florian.kirmaier at gmail.com>
>>>     <mailto:florian.kirmaier at gmail.com>
>>>     *Date: *Tuesday, 2022/09/13 at 08:11
>>>     *To: *openjfx-dev at openjdk.java.net
>>>     <openjfx-dev at openjdk.java.net> <mailto:openjfx-dev at openjdk.java.net>
>>>     *Subject: *Provide Quit handler for system menu bar
>>>
>>>     Hi Everyone,
>>>
>>>
>>>     In one project, we have to handle the quit-logic for MacOS
>>>     ourselves,
>>>     when the <quit app> menu entry is used.
>>>     As background information - this menu entry is set in the
>>>     class com.sun.glass.ui.mac.MacApplication.
>>>     It's basically hard coded. Currently, in this project, the menu
>>>     entry doesn't work in some cases.
>>>
>>>     My Solution would be:
>>>
>>>     Provide a method "Platform.setQuiteHandler(Supplier<Boolean>)"
>>>     This handler is called when quit <appname> from the menu is called.
>>>     If the handler returns true, all windows are closed. Otherwise,
>>>     nothing happens.
>>>
>>>     It would look like the following:
>>>     ```
>>>     /**
>>>      * Sets the handler to be called when the application is about
>>>     to quit.
>>>      * Currently, this can only happen on MacOS.
>>>      *
>>>      * This handler is called, when the user selects
>>>      * the "Quit <appname>" from the application menu.
>>>      * When the provided handler returns true,
>>>      * the application will close all windows.
>>>      * If the handler returns false, the application will not quit.
>>>      *
>>>      * @param The new quit handler.
>>>      */
>>>     public static void setQuitHandler(Supplier x) {
>>>         ...
>>>     }
>>>     ```
>>>     I've created a ticket for this topic.
>>>     https://bugs.openjdk.org/browse/JDK-8293700
>>>
>>>
>>>     I've got a working version for this change.
>>>
>>>     According to Kevin Rushforth this need a prior dicussion on the
>>>     mailing list.
>>>
>>>     Any opinion regarding this?
>>>
>>>     I could provide a pullrequest, if someone is interested.
>>>
>>>     Florian Kirmaier
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20220920/81f69b2d/attachment-0001.htm>


More information about the openjfx-dev mailing list