RFR: 8313424: JavaFX controls in the title bar [v3]

Michael Strauß mstrauss at openjdk.org
Tue Oct 22 15:23:39 UTC 2024


On Sun, 20 Oct 2024 01:23:01 GMT, Michael Strauß <mstrauss at openjdk.org> wrote:

>> This PR is a new take on a highly requested feature: JavaFX controls in the header bar (see also #594 for an earlier iteration).
>> 
>> This is a feature with many possible ways to skin the cat, and it has taken quite a bit of effort to come up with a good user model. In contrast to the previous iteration, the focus has shifted from providing an entirely undecorated window to providing a window with a user-configurable header bar.
>> 
>> The customizable header bar is a new layout container: `javafx.scene.layout.HeaderBar`. It has three areas that accept child nodes: leading, center, and trailing.  `HeaderBar` also automatically adjusts for the placement of the default window buttons (minimize, maximize, close) on the left or right side of the window.
>> 
>> The customizable header bar is combined with a new `EXTENDED` stage style, which extends the client area into the header bar area. The new extended stage style is supported on Windows, macOS, and Linux. For platforms that don't support this stage style, it automatically downgrades to `DECORATED`.
>> 
>> This is how it looks like on each of the three operating systems:
>> 
>> ![extendedwindow](https://github.com/user-attachments/assets/9d798af6-09f4-4337-8210-6eae91079d3a)
>> 
>> The window buttons (minimize, maximize, close) are provided by JavaFX, not by the application developer. This makes it easier to get basic window functionality without recreating the entirety of the window controls for all platforms.
>> 
>> ## Usage
>> This is a minimal example that uses a custom header bar with a `TextField` in the center area. `HeaderBar` is usually placed in the top area of a `BorderPane` root container:
>> 
>> public class MyApp extends Application {
>>     @Override
>>     public void start(Stage stage) {
>>         var headerBar = new HeaderBar();
>>         headerBar.setCenter(new TextField());
>> 
>>         var root = new BorderPane();
>>         root.setTop(headerBar);
>> 
>>         stage.setScene(new Scene(root));
>>         stage.initStyle(StageStyle.EXTENDED);
>>         stage.show();
>>     }
>> }
>> 
>> To learn more about the details of the API, refer to the documentation of `StageStyle.EXTENDED` and `HeaderBar`.
>> 
>> ## Platform integration
>> The implementation varies per platform, and ranges from pretty easy to quite involved:
>> 1. **macOS**: The window buttons are provided by macOS, we just leave an empty area where the window buttons will appear. The client area is extended to cover the entire window by setting the `NSW...
>
> Michael Strauß has updated the pull request incrementally with one additional commit since the last revision:
> 
>   revert unintended change

I would advise all commenters to look at the proposal which is presented, understand the trade-offs being made, and only then criticize the design decisions and offer suggestions.

This feature is designed in a particular way because it needs to work on _all_ supported platforms (not just the one you happen to like most). Here are the main design decisions that I made along the way:

### Multi-platform
Since JavaFX is a multi-plattform framework, this feature _must_ work out of the box on all supported platforms. It is a non-starter to require application developers to add platform-specific code to their applications if they want to use this feature.

This rules out things like requiring developers to add JavaFX shadows to their application because Linux doesn't provide the shadows for us. If we require JavaFX shadows, we must do that without intervention of application developers. We also shouldn't add platform-specific configuration switches.

### Ease of use
It must be easy to use. In particular, this means that default window interactions must work reliably and feel at home on the OS. If possible, we will use platform-native window buttons instead of crafting our own bespoke versions (the macOS implementation does just that).

If you look at many examples of applications that extend the client area into the title bar, you will notice that most good examples don't re-invent window buttons in their totality, but either use platform-native buttons or at least use lookalike-versions of the platform buttons.

Window buttons require quite a bit of effort to get it just right. It's way more effort than just throwing a bunch of buttons in the window corner and calling it a day. Window buttons need to interact with the OS in very specific ways to enable features like snap layouts (on Windows). Again, please understand the design constraints before offering alternatives.

### Customizability
It is an explicit non-goal of this PR to offer a way to customize the window buttons. That's because at least on macOS, there is simply no way to do that with the OS-native buttons. If we allowed for customization only for Windows and Linux, but not for macOS, we would again run into the problem of falling short of our multi-platform compatibility goal.

In addition to that, most application developers will not want to customize the window buttons. Just look at the examples of applications that have already been posted, and you'll notice that window buttons are not gratuitously different, they at least try to feel at home on the target OS.

Shifting all of the implementation burden for window buttons to application developers is the wrong framing for this feature. We're not trying to build a feature that mainly caters to the few applications with crazy custom user interfaces, we're trying to build a feature for the 99%.

-------------

PR Comment: https://git.openjdk.org/jfx/pull/1605#issuecomment-2429579311


More information about the openjfx-dev mailing list