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