Skip to content
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

Custom Window Title bar and Frame API proposal. #2521

Open
LouChiSoft opened this issue Apr 10, 2023 · 4 comments
Open

Custom Window Title bar and Frame API proposal. #2521

LouChiSoft opened this issue Apr 10, 2023 · 4 comments
Labels
rfc Request for comments: proposals for changes

Comments

@LouChiSoft
Copy link

Title bar and Frame Proposal
I noticed that there have been several tickets related to custom title bars, being able to resize a frameless window, etc. for example #610, #613 and #2367. But I haven't seen a detailed proposal for an API that could address these missing features. So here is my proposal for an API that will hopefully cover all scenarios for custom title bars and frames so users can easily customise their windows. I should point out that I am relatively new to Slint, so my .slint API usage may not be perfect, but so far have been really enjoying the API and think that these improvements would really push it ahead for GUIs in Rust.

The customisation would be broken down into a TitleBar and Frame on the Window element. If the user doesn't manually set these then they will have native style and behaviour to that platform. If the user defines a custom TitleBar or Frame then they can set it on the Window to create a custom Window class.

TitleBar
The title bar contains a property for the height of the title bar and is the width of the Window. The title bar would automatically provide similar behaviour to TouchArea that when clicked moves the window like a standard title bar would. The user would then be able to define custom buttons that replace the standard window decorations (either left or right), or even create something like a tab line as well.
Example:

component CustomTitleBar inherits TitleBar {
    height: 32px;
    background: #00A2E8;
    /* Buttons and other elements to create decorations and tab lines, etc. */
}

Frame
Similar to the title bar the user would define a custom frame with some basic properties and the behaviour would me aligned to match those properties. For the frame this would be the border width, colour, corner overlap, etc. that would be used to automatically create resizing logic that matches the border the user creates. Also similar to the custom title bar, the width of the top and bottom border and the height of the left and right borders would be sized to match the window and wouldn't need to be defined by the user. If the user wanted to they could create a border that has resize logic, but is otherwise invisible by making the background transparent. The border would then be turned off whenever the window is maximized to match standard window behaviour.
Example:

component CustomFrame inherits Frame {
    left: 2px;
    right: 2px;
    top: 2px;
    bottom: 2px;
    background: #00A2E8FF;
}

Example use cases
Here are some example use cases for how one could use the API. It's not fully detailed but it should be enough to get the gist of how the user is expected to use it. I tried to use bright colours on a black background to make the differences more noticeable, mainly for the frame.

Style Behaviour Example .slint code Reference Image
Title Bar: Native
Frame: Native
Moveable: True
Resizable: True
export component MainWindow inherits Window {
}
standard
Title Bar: Native
Frame: None
Moveable: True
Resizable: False
export component MainWindow inherits Window {
frame: NoFrame;
}
no-frame
Title Bar: None
Frame: Native
Moveable: False
Resizable: True
export component MainWindow inherits Window {
title-bar: NoTitleBar;
}
no-title-bar
Title Bar: Native
Frame: Custom
Moveable: True
Resizable: True
export component MainWindow inherits Window {
frame: CustomFrame;
}
standard-title-bar-custom-frame
Title Bar: Custom
Frame: Native
Moveable: True
Resizable: True
export component MainWindow inherits Window {
title-bar: CustomTitleBar;
}
custom-title-bar-native-frame
Title Bar: Custom
Frame: Custom
Moveable: True
Resizable: True
export component MainWindow inherits Window {
title-bar: CustomTitleBar;
frame: CustomFrame;
}
custom-title-bar-custom-frame

I would have really like to have also presented maybe an example implementation, but when it comes to windowing APIs, especially native ones, I don't really have enough knowledge/experience to provide one. Hopefully my proposal is detailed enough that someone better than me could validate the idea.

I'm open to questions and discussions about the proposal

@tronical tronical added the rfc Request for comments: proposals for changes label Apr 11, 2023
@tronical
Copy link
Member

Thank you for your proposal. I've marked this issue with the rfc label - this is a great starting point of discussion.

I quite like the idea of being able to customise all the way to a custom frame. In terms of API, currently we don't support properties that can take enum values (like frame: NoFrame;) as well as the name of components (frame: CustomFrame;).

In the spirit of the Dialog element, perhaps this could be done by the compiler looking at the children of the Window?

So for example:

export component MainWindow inherits Window {
    no-frame: true;
    CustomFrame { ... }
}

would re-use the existing API to say: Don't show a system provided frame, but instead draw my own custom window frame.

Or should we deprecate no-frame perhaps?

@LouChiSoft
Copy link
Author

LouChiSoft commented Apr 11, 2023

Hi, I see the issue with the Enum/Components. But what if I suggested that NoFrame and NoTitleBar were actually pre-defined children of Frame and TitleBar included with Slint. For example: export component NoFrame inherits Frame and export component NoTitleBar inherits TitleBar and they would define an empty version of each. That way you are only using components and don't have to worry about Enums.

I'm afraid I haven't used the Dialog element to know if it could be implemented in a similar way.

@ogoffart
Copy link
Member

Why do we even need Frame and TitleBar to be special?
But i think some WM support adding buttons or menu within the titlebar while still keeping it a native title bar.

@LouChiSoft
Copy link
Author

LouChiSoft commented Apr 12, 2023

Why do we even need Frame and TitleBar to be special?

My main reason is for reusability. You might have different type of windows that all have a frame but different title bars. Sure you could have a single object that combines the two, but if you then decided that you wanted to update the frame to be different you would have to change all your custom frames to match. This way you only have to define the frame once per style of frame you intend to use (which I expect to be 1 in most applications) and then when you update it, it updates all windows using that frame.

But I think some WM support adding buttons or menu within the titlebar while still keeping it a native title bar.

Very true, but I do feel there is still value in being able to have the same title bar across all OSes. I know I personally prefer when software I use on multiple OSes looks the same visually. That way I don't have to learn where things are per platform. I know that might seem like a small thing, but it can really make an application more approachable when you work on multiple platforms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rfc Request for comments: proposals for changes
Projects
None yet
Development

No branches or pull requests

3 participants