On Fri, 1 Nov 2024 23:38:52 GMT, Michael Strauß <mstra...@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 with a new target base due to a 
> merge or a rebase. The pull request now contains 23 commits:
> 
>  - Merge branch 'master' into feature/extended-window
>  - Merge branch 'master' into feature/extended-window
>  - macOS: dynamically adapt toolbar style to headerbar height
>  - fix header bar height flicker
>  - NPE
>  - fix peer access outside of synchronizer
>  - improve title text documentation
>  - macOS: hide window title
>  - better documentation
>  - set minHeight to native height of title bar
>  - ... and 13 more: https://git.openjdk.org/jfx/compare/58cd76a8...9b63892d

I'm not sure if it's feasible, but having a `GtkOverlay` seems to work on a 
basic app paintable C app:


#include <gtk/gtk.h>

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr) {
    cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
    cairo_paint(cr);

    return FALSE;
}

static void create_overlay(GtkWidget *window) {
    GtkWidget *overlay;
    GtkWidget *hb;

    overlay = gtk_overlay_new();
    gtk_container_add(GTK_CONTAINER(window), overlay);

    hb = gtk_header_bar_new();
    gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(hb), TRUE);
    gtk_header_bar_set_has_subtitle(GTK_HEADER_BAR(hb), FALSE);
    gtk_header_bar_set_custom_title(GTK_HEADER_BAR(hb), NULL);
    gtk_overlay_add_overlay(GTK_OVERLAY(overlay), hb);

    gtk_widget_set_valign(hb, GTK_ALIGN_START);
    gtk_widget_set_halign(hb, GTK_ALIGN_END);
}

int main(int argc, char *argv[]) {
    GtkWidget *window;

    // Initialize GTK
    gtk_init(&argc, &argv);

    GtkCssProvider *css_provider = gtk_css_provider_new();
    gtk_css_provider_load_from_data(css_provider,
        "headerbar {"
        "  background-color: rgba(255, 255, 255, 0.0);"
        "}",
        -1, NULL);

    gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
                                              GTK_STYLE_PROVIDER(css_provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_USER);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Test");
    gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);

    gtk_widget_set_app_paintable(window, TRUE);

    g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(on_draw_event), NULL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), 
NULL);
    create_overlay(window);
    gtk_widget_show_all(window);


    gtk_main();

    return 0;
}


Gtk4 even has 
[WindowControls](https://docs.gtk.org/gtk4/class.WindowControls.html). 

I started to play with the CSS to make it transparent, but it does not seem 
much straightforward, but possible.

Running the program with `GTK_DEBUG=interactive` makes it easier.

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

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

Reply via email to