All of these requests seem to map to what we added to AWT in JDK 9.
We did this because there'd been Apple specific APIs that came in via the
Apple port but were very iffy in terms of what was supported and it was
not a good idea to formally export them from the new desktop module.
The java.awt.Desktop class was enhanced by the java.awt.desktop package
and all of these things are provided in a platform neutral way.
You just query whether the support is available.
These can even be used in a mixed AWT/FX application if you want a
solution now,
but FX could have its own version of these.
Nothing that mentions a platform (please!).
-phil
On 9/20/22 6:38 AM, Scott Palmer wrote:
I always understood Alt+F4 as simply being a keyboard shortcut on
Windows for closing the window of the active application. The same as
clicking the close widget. I don’t think there is anything special
about it. As far as being an equivalent to the macOS Quit action, I
don’t think it is quite the same. Does an application even know the
difference between a window closed with the widget vs. Alt+F4? CTRL+F4
closes the current document window or tab - similar to Command-W on
macOS.
I’m not aware of any special handlers being called on Windows for
these shortcuts other than what is called when the equivalent close
widget is pressed. If I’m wrong about that, then sure, a quit handler
for JavaFX could be wired in to the same mechanism automatically.
Maybe Linux has an equivalent as well, I don’t know.
While we are at it, custom handling for the ‘About’ menu item in the
application menu is also needed, is it not?
For now I’m currently using Jan Gassen’s port of NSMenuFX to hook into
this stuff. https://github.com/0x4a616e/NSMenuFX
Scott
On Sep 20, 2022, at 5:55 AM, John Hendrikx <[email protected]>
wrote:
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
<[email protected]> 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 <[email protected]> on behalf of
Kevin Rushforth <[email protected]>
*Date: *Monday, 2022/09/19 at 09:33
*To: *[email protected] <[email protected]>
*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 <[email protected]>
<mailto:[email protected]> on behalf of Florian
Kirmaier <[email protected]>
<mailto:[email protected]>
*Date: *Tuesday, 2022/09/13 at 08:11
*To: *[email protected]
<[email protected]>
<mailto:[email protected]>
*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