RFR: 8359601: Fix window button states of an extended stage
Cormac Redmond
duke at openjdk.org
Mon Jun 16 23:11:34 UTC 2025
On Sun, 15 Jun 2025 20:01:11 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.
> 2. The disabled states of `HeaderButtonOverlay` as well as `HeaderButtonBehavior` are changed to mat...
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 `dialog.initStyle(StageStyle.EXTENDED)` to see difference.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class MinimiseIconEnabledBug extends Application {
@Override
public void start(Stage primaryStage) {
Button button = new Button("Click");
button.setOnAction(e -> {
final Dialog<Object> dialog = new Dialog<>();
dialog.initOwner(primaryStage);
// Existing behaviour: minimise icon disabled when commented
// Possible "bug": Minimise icon enabled when uncommented
// dialog.initStyle(StageStyle.EXTENDED);
dialog.initModality(Modality.NONE);
dialog.setResizable(true); // This is important
dialog.setTitle("My Dialog");
dialog.setContentText("Lorem ipsum dolor sit amet, consectetur adipiscing...");
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK);
dialog.show();
});
StackPane root = new StackPane(button);
Scene scene = new Scene(root, 300, 200);
primaryStage.setTitle("My First JavaFX App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
-------------
PR Comment: https://git.openjdk.org/jfx/pull/1831#issuecomment-2978439674
More information about the openjfx-dev
mailing list