RFR: 8359601: Fix window button states of an extended stage [v6]
Cormac Redmond
duke at openjdk.org
Tue Jun 24 08:20:37 UTC 2025
On Sat, 21 Jun 2025 23:37:13 GMT, Michael Strauß <mstrauss at openjdk.org> wrote:
>> The window button states (disabled/hidden) of extended stages with a `HeaderButtonOverlay` or 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
>>
>> | Window attributes | Iconify | Maximize | Close |
>> |---|---|---|---|
>> | resizable, not modal | visible | visible | visible |
>> | not resizable, not modal | visible | visible, disabled | visible |
>> | resizable, modal | visible, disabled | visible | visible |
>> | not resizable, modal | hidden | hidden | visible, utility-style |
>>
>> #### Ubuntu 24 / Fedora 41 (GNOME)
>>
>> | Window attributes | Iconify | Maximize | Close |
>> |---|---|---|---|
>> | resizable, not modal | visible | visible | visible |
>> | not resizable, not modal | visible | hidden | visible |
>> | resizable, modal | visible, _not working_ | visible, _not working_ | visible |
>> | not resizable, modal | visible, _not working_ | hidden | visible |
>>
>> #### Kubuntu 24 (KDE)
>>
>> | Window attributes | Iconify | Maximize | Close |
>> |---|---|---|---|
>> | resizable, not modal | visible | visible | visible |
>> | not resizable, not modal | visible | hidden | visible |
>> | resizable, modal | visible, _not working_ | visible | visible |
>> | not resizable, modal | visible, _not working_ | hidden | visible |
>>
>> ## Observations
>>
>> 1. On Windows, buttons are generally disabled when their operation is not possible with the given window attributes.
>> * Exception: modal/non-resizable windows look like utility windows (iconify and maximize are hidden)
>> 2. On GNOME and KDE, buttons are generally hidden when their operation is not possible.
>> * Exception: iconify and maximize on modal windows is not hidden, but seems to simply not do anything (bug?)
>>
>> ## 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:
>>
>> | Window attributes | Iconify | Maximize | Close |
>> |---|---|---|---|
>> | resizable, not modal | yes | yes | yes |
>> | not resizable, not modal | yes | no | yes |
>> | resizable, modal | no | yes | yes |
>> | not resizable, modal | no | no | yes |
>>
>> ## Fixes
>>
>> This PR includes the following changes:
>> 1. Unused code relating to window modality is removed...
>
> Michael Strauß has updated the pull request incrementally with one additional commit since the last revision:
>
> fix resizable state of macOS window
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).
public class DisappearingHeaderBarNodesBug extends Application {
@Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Button button = new Button("Click for "bug()"!");
button.setOnAction(_ -> bug(root));
root.setCenter(new VBox(new Label("Something above"), button, new Label("Something below")));
root.setTop(getHeaderBar());
primaryStage.initStyle(StageStyle.EXTENDED);
primaryStage.setScene(new Scene(root, 300, 200));
primaryStage.show();
}
// Wrapping the root node in a stackpane is common
private void bug(Pane root) {
StackPane stackPane = new StackPane();
root.getScene().setRoot(stackPane);
stackPane.getChildren().addFirst(root);
}
private HeaderBar getHeaderBar() {
HeaderBar headerBar = new HeaderBar();
headerBar.setCenter(new Label("!!! HeaderBar !!!"));
headerBar.setLeading(new Label("L"));
return headerBar;
}
public static void main(String[] args) {
launch(args);
}
}
As you can see, after you click the button, and resize, the HeaderBar can disappear completely:
https://github.com/user-attachments/assets/93a320a5-0010-4941-a2a4-9e0e65cbd57d
-------------
PR Comment: https://git.openjdk.org/jfx/pull/1831#issuecomment-2999295206
More information about the openjfx-dev
mailing list