-
Notifications
You must be signed in to change notification settings - Fork 541
8359601: Fix window button states of an extended stage #1831
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
|
/reviewers 2 |
|
👋 Welcome back mstrauss! A progress list of the required criteria for merging this PR into |
|
@mstr2 This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 27 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
Webrevs
|
|
Most of this seems to be working well! But I have found a likely bug. Hopefully fairly self-explanatory from the code. Minimise icon is normally disabled, but still enabled when EXTENDED is used & when dialog is resizable. Just flip comment on |
|
Another suspected issue (not really related to this PR), close request handlers are not called when using EXTENDED. E.g.: Same for dialogs... |
|
Good catch, a non-modal owned window also can't be iconified. I've added code and tests for this scenario. |
Sample: |
|
I've filed another ticket for that: JDK-8359763. |
Looks good, can't find anymore issues... |
|
JavaFX modal windows are not native modals, as evidenced by the code removal on this PR (it's not used) . On GNOME, native modal windows automatically remove the minimize and maximize buttons. I did an experiment and found that it's possible to get native modal windows (at least with GTK Glass) by passing the modality flag from |
That's a good idea for an enhancement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updated behavior looks good on windows 11, I tested various combinations of modal/owned/resizable/StageStyle settings, including modifying the resizeable bit when a stage is already showing.
I also checked the behavior in macOS Sequoia 15.5. There, a window where setResizable(false) is called before showing the stage, unexpectedly has a working maximize button even without StageStyle.EXTENDED.
Looks like this was not the case prior to the integration of #1605, so this behavior was probably introduced there and may need a fix in this PR or elsewhere.
I don't see any code using the java and native enterModal/exitModal methods which were removed, so this looks like a safe change.
Finally, I left some comments regarding potentially confusing definitions of modal, otherwise the code looks good.
| private Node buttonAtMouseDown; | ||
|
|
||
| public HeaderButtonOverlay(ObservableValue<String> stylesheet, boolean utility, boolean rightToLeft) { | ||
| public HeaderButtonOverlay(ObservableValue<String> stylesheet, boolean modal, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a bit confusing to have isModal in Window and getModality in Stage on one hand, and a modal field / parameter here, which is set to isModal() || getOwner() != null by callers. Maybe clarify by renaming to something like effecitvelyModal or modalOrOwned?
| if (!node.disableProperty().isBound()) { | ||
| node.setDisable(resizable == Boolean.FALSE); | ||
| boolean utility = stage.getStyle() == StageStyle.UTILITY; | ||
| boolean modal = stage.getOwner() != null || stage.getModality() != Modality.NONE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in case HeaderButtonOverlay.modal is renamed, this variable could be renamed in the same way.
| } | ||
|
|
||
| final boolean resizable; | ||
| final boolean modal; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
Just curious, why a separate bug for this instead of fixing in this PR and avoiding the headaches/conversations of more PRs -- is it more complicated that it sounds? |
Shorter PRs tend to get more timely reviews. That being said, since it is closely related, I've added the fix to this PR. /issue add JDK-8359763 |
|
@mstr2 |
The implementation relied on the |
drmarmac
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good, all combinations that I've tested manually seem to work fine now. I also tested with gnome & KDE this time.
|
I have found another bug/issue, which is again related to wrapping a root node in a StackPane (something that is common in, for example, ControlsFx). Although the observed behaviour is probably strictly logically correct, I think this should be prevented (e.g, HeaderBar has/gets special meaning/treatment). As you can see, after you click the button, and resize, the HeaderBar can disappear completely: bug.mp4 |
|
@credmond We should keep this PR focused, let's use the mailing list or JBS to discuss other issues. |
|
FYI to any reviewer: I've been using this branch's EXTENDED/HeaderBar extensively now without any new issues... |
|
I think this fix should make the 25 release if possible, as it would be unfortunate to preview the new feature with distracting bugs included. The fix is also quite well-tested at this point. @kevinrushforth @andy-goryachev-oracle Do you have any review capacity to spare for this within the current RDP? |
Agreed. It wouldn't take long until others come across this and raise the same issue. |
Yes, I'll review it this week. It seems a good candidate for backporting to jfx25. |
| } | ||
|
|
||
| if (type == HeaderButtonType.MAXIMIZE) { | ||
| subscription = Subscription.combine(subscription, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here and on L66 the subscription pointer (set in L61) gets overwritten. does it mean some subscription(s) won't be cancelled in dispose()?
edit: please disregard, I see it's combining subscriptions.
kevinrushforth
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good. I submitted a set of headful test jobs and will report when done. I want to do a little light manual testing, especially on macOS where there are a few changes in the non-extended case (although the code looks equivalent).
| } | ||
|
|
||
| - (void)_setResizable | ||
| - (void)_setResizable:(bool)resizable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good. It definitely seems cleaner to pass in resizable as a parameter rather than having this method be a "toggle" resizable as it was previously.
| { | ||
| [window performSelectorOnMainThread:@selector(_setResizable) withObject:nil waitUntilDone:YES]; | ||
| } | ||
| [window _setResizable:jResizable]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume you removed the performSelectorOnMainThread because the calling method always calls this on the main thread?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is a call that always happens on the FX thread as a result of calling javafx.stage.Window.show(). This is verified just a few lines earlier with GLASS_ASSERT_MAIN_JAVA_THREAD (that's always been there, I didn't add it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, the calling Java code does a thread check. So we're good.
|
The headful CI tests passed on Linux and macOS (I will need to manually run it on Windows). |
|
Headful tests passed on Windows. |
|
/integrate |
|
Going to push as commit bc433da.
Your commit was automatically rebased without conflicts. |
|
/backport jfx jfx25 |
|
@mstr2 the backport was successfully created on the branch backport-mstr2-bc433da8-jfx25 in my personal fork of openjdk/jfx. To create a pull request with this backport targeting openjdk/jfx:jfx25, just click the following link: The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:
If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jfx: |
|
Hi @kapilkumar9976, thanks for making a comment in an OpenJDK project! All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user kapilkumar9976" for the summary. If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.
Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use. |

The window button states (disabled/hidden) of extended stages with a
HeaderButtonOverlayor custom header buttons are inconsistent with what we would expect from the OS (Windows and Linux). To figure out what we would expect, I started with gathering some data. The following table shows the button states of system-decorated windows on various platforms:Windows 11
Ubuntu 24 / Fedora 41 (GNOME)
Kubuntu 24 (KDE)
Observations
Permitted window button operations
Given the gathered observations and some simple logic, this is the table of operations that are permitted for all combinations of modal and resizable window attributes:
Fixes
This PR includes the following changes:
HeaderButtonOverlayas well asHeaderButtonBehaviorare changed to match the table above.Progress
Issues
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/1831/head:pull/1831$ git checkout pull/1831Update a local copy of the PR:
$ git checkout pull/1831$ git pull https://git.openjdk.org/jfx.git pull/1831/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 1831View PR using the GUI difftool:
$ git pr show -t 1831Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/1831.diff
Using Webrev
Link to Webrev Comment