-
Notifications
You must be signed in to change notification settings - Fork 534
8359108: Mac - When Swing starts First, native application menu doesn't work for JavaFX #1835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
👋 Welcome back pabulaner! A progress list of the required criteria for merging this PR into |
❗ This change is not yet ready to be integrated. |
Webrevs
|
I'm not at all sure this fix is the right thing to do. |
If You mean it why I didn't fix it there the answer is that when You have for example two screens and You switch from a Swing window that is in the first screen to a other unrelated window in another screen, the menu bar should stay in the first screen. If Swing would remove the menu items on focus loss, this menu would be gone as well. If You mean it as a edge case and if my code would handle it correctly, it would, as it just removes all items not owned by JavaFX and so if there are no menus that fall in that category, it simply will do nothing. |
Any fix that happens inside Glass is the wrong fix. I think I have an idea of what’s happening under the hood with this PR. When a JavaFX window loses focus JavaFX removes most of the items from NSApp.mainMenu. I suppose when the Swing window gains focus Swing is re-writing most of NSApp.mainMenu without JavaFX knowing about it. And the same thing is happening when focus moves from a Swing window to a JavaFX window. So window focus is being used as an informal protocol to determine whether Swing or JavaFX controls most of the system menu. This will all break down with the application menu, the first menu in the menu bar after the Apple logo menu. That one requires special handling since it must be present at all times. JavaFX sets that up once and never touches it again. I don’t know how Swing handles this menu but I’m guessing it does something similar. It looks like this PR is removing the Swing items from the application menu so JavaFX can re-populate it. Or something like that. It doesn’t matter. If you want Swing and JavaFX to coordinate on the system menu there needs to be a formal protocol for doing so and that formal protocol must take into account the special needs of the application menu. Neither system should be messing around at the platform level adding and removing the other guy’s menu items. JavaFX is not designed to support that sort of manipulation and I doubt Swing is either. If it works it’s entirely by accident. |
So if I understand Your suggestion correctly, I should implement an event like system that allows Swing and JavaFX to communicate with each other. So JavaFX can send an event to Swing when it wants to take control of the menu bar and vice versa. Did I understand this correctly? |
I agree with @prrace and @beldenfox, this looks like the wrong fix. The application should decide which part of it controls the system menu and coordinate within itself which part supplies and handles the menu items. |
But how should it decide this? Because if You have for example a Swing window and a JavaFX window both should be able to set the native menu bar on MacOS when they gain focus. At least this would make the application look consistent. Although it is discouraged to use AWT / Swing and JavaFX together, in some cases it can't be avoided due to the need to use some AWT or Swing functionality alongside with JavaFX. So I would be really grateful if You would have some suggestions or point me in the right direction what would be an acceptable approach to fix this issue. |
what comes to mind:
|
The interface you want to look at is TKSystemMenu. When JavaFX wants to install a set of Menus in the system menu this is the interface it uses. The best way to do this is to take the menus passed into TKSystemMenu, create Swing equivalents, and then install them in a Swing menubar. That way only Swing is manipulating the system menu. Unfortunately this is a lot of work in part because it's not a one-time conversion. The system menu machinery is expected to track changes made to the JavaFX menus so there are a lot of delegates and listeners involved. Fortunately there's a working example in GlassSystemMenu you can use for reference. I haven't looked into the threading issues involved here (and I'm sure there are some). I don't think it's a good idea to try to switch control of NSApp.mainMenu between JavaFX and Swing. Under the hood they have very different ways of manipulating the mainMenu and their own assumptions about how the application menu works. And frankly you should never allow JavaFX to show its application menu in a Swing app since the JavaFX version has serious limitations. I'm working on fixing that but for now it's best that Swing is in charge of the system menu. |
The model we are trying to have here is quite simple. Background Actually, we only wanted to make the JavaFX menu work when Swing/AWT was started first. Test I hope these tests will improve the confidence, that this solution is correct and maintainable. |
@pabulaner This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply issue a |
@pabulaner This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
…'t work for JavaFX
/open |
1 similar comment
/open |
@pabulaner This pull request is now open |
@pabulaner This pull request is already open |
@pabulaner Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration. See OpenJDK Developers’ Guide for more information. |
I have rewritten the entire fix so that it requires only a few and clear changes in the source code. It is now able to handle multiple AWT and JFX windows that have all installed a native system menu without them interfering with each other. I have also added 3 test cases to show that the change works as expected:
|
…'t work for JavaFX
…'t work for JavaFX
…'t work for JavaFX
Using osascript to check the state of the menus is a great idea (assuming there's no policy against using that sort of thing in the system tests). Far better than what I did in PR #1881. You need to have folks on the AWT/Swift side review this new approach. If I understand this correctly when the JavaFX window assumes focus you're stashing away NSApp.mainMenu under the assumption that it was put there by AWT. Then you're replacing it with an NSMenu built by JavaFX. When the JavaFX window loses focus you're putting the stashed AWT NSMenu back into NSApp.mainMenu. The two big questions are: a) Will AWT malfunction since NSApp.mainMenu no longer points to the NSMenu they expect? Put another way, JavaFX currently uses window focus to figure out which window should "own" NSApp.mainMenu and this PR extends that notion to include Swing windows. I'm not sure that's matches how AWT works internally so someone on the AWT side needs to weigh in. What you're doing on the JavaFX side is just some pointer shuffling. Swapping NSApp.mainMenu in and out makes me uneasy but it's hard for me to point to a specific problem that will arise on the JavaFX side. There's also the larger question of whether we want to support this configuration to begin with. |
I decided to close this PR and to open a new one after discussing it with @FlorianKirmaier as we both think this will simplify things. This PR contains a lot of comments on the first version of the fix and since it was entirely rewritten makes it unnecessarily complex. |
I have now created the new PR: #1904 I also have taken into account the very good advice to let the AWT devs take a look at the PR and stated what the fix does , how it works and why we need this fix. |
This pull request fixes the system menu bar on Mac when combining windows of Swing and JavaFX.
The first issue was to get the native menu bar working simultaneously on Swing and JavaFX, which was done by just returning always true inside the supportsSystemMenu method.
The second issue was to remove all system menu items installed by a swing window. This was fixed by checking the system menu bar every time an item is inserted or removed and removing all menu items that are not owned by JavaFX. This check is done on every insert and remove as JavaFX does not have a clear method inside the MenuBarDelegate class that could be called every time the window gets the focus.
I tested the fix with two Swing and two JavaFX windows that are run inside the same application and it worked without any errors, but on further testing I noticed some issues with the menu bar. I am currently writing the test and fixes for it.
Co-Author: @FlorianKirmaier
Progress
Issue
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/1835/head:pull/1835
$ git checkout pull/1835
Update a local copy of the PR:
$ git checkout pull/1835
$ git pull https://git.openjdk.org/jfx.git pull/1835/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 1835
View PR using the GUI difftool:
$ git pr show -t 1835
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/1835.diff
Using Webrev
Link to Webrev Comment