-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Feature request: Add setting for titlebar style with native window controls support #2663
Comments
Any progress? |
Would love to see progress on this too, it's an important feature for me. |
@chhpt @gardc we're still mainly blocked by the feature freeze here. The audit process is coming to an end and with the 1.0 release being so close, we're completely focused on that one. Btw, if someone wants to help us out and take a stab at implementing this feature, we always appreciate PRs! ❤️ |
I will tackle this one. On my roadmap this week. |
@FabianLars Thank you for the update, it's much appreciated. Can't wait to see whats in store for 1.0! @JonasKruckenberg Great to hear! Let me know if there's anything I can do to assist with regards to macOS side of things. |
Hello, The feature will come in tauri 2.0 or use tauri-plugin to complete it? |
Alright, here goes my issue-only knowledge dump 😂: I'm struggling a bit with implementing this in tauri+tao directly, but here is how you can implement this yourself using the use cocoa::appkit::{NSWindow, NSWindowStyleMask};
use tauri::{Runtime, Window};
pub trait WindowExt {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, transparent: bool);
}
impl<R: Runtime> WindowExt for Window<R> {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, transparent: bool) {
use cocoa::appkit::NSWindowTitleVisibility;
unsafe {
let id = self.ns_window().unwrap() as cocoa::base::id;
let mut style_mask = id.styleMask();
style_mask.set(
NSWindowStyleMask::NSFullSizeContentViewWindowMask,
transparent,
);
id.setStyleMask_(style_mask);
id.setTitleVisibility_(if transparent {
NSWindowTitleVisibility::NSWindowTitleHidden
} else {
NSWindowTitleVisibility::NSWindowTitleVisible
});
id.setTitlebarAppearsTransparent_(if transparent {
cocoa::base::YES
} else {
cocoa::base::NO
});
}
}
} This is how you would use the defined function in your app to make a window have a transparent titlebar. fn main() {
tauri::Builder::default()
.setup(|app| {
let win = app.get_window("main").unwrap();
win.set_transparent_titlebar(true);
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
} |
but I not found API to hide toolbar(close maxsize fullsize button ) , if can hide the button, it will is perfect ! |
This can be archived with the same NSWindowStyleMask that I used in the above example if you merely want to "grey-out" the minimize and close buttons. If you're looking to hide all window buttons you should have chosen |
yes, I have use the API, it equal to setting tauri.conf.json "decoration" = false, but the setting will let window border lose round |
Do you want to publish your app to the macOS App Store? If not you can use |
the solution I found it in tauri document (https://tauri.studio/docs/guides/window-customization) ,but not perfect ,when I drag my windows , the border have display blank block on border. I want a setting can hide button and have round border(the style like native swift ui on mac) Yes, I want publish to App Store , Why rust need use private API, but use swift or electron can ? |
hello, I found the mask will let mouse can't move the window, it is indeterminacy for me is Bug or macos feauter, Can you give me a suggestion ? NSWindow::setTitlebarAppearsTransparent_(id, cocoa::base::YES);
let mut style_mask = id.styleMask();
style_mask.set(
NSWindowStyleMask::NSFullSizeContentViewWindowMask,
transparent,
);
id.setStyleMask_(style_mask); I try call the possiable API but not work id.setMovable_(cocoa::base::YES);
id.setMovableByWindowBackground_(cocoa::base::YES); I use create a empty div and use <body>
<div data-tauri-drag-region style="height:30px">
</div>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body> |
You need the |
ok, I now setting tauri->allowlist is "all" and don't need the setting up again ,but this is good suggestion, this the doc |
Great!
|
This is not a thing on windows as far as I'm aware. The common practice (with electron too) seems to be to remove decorations entirely and create the titlebar from scratch using html/css/js |
Got it. Thank you! On Windows, removing decorations entirely and creating the titlebar from scratch using html/css/js, traffic lights can still be used even if the underlying application becomes inactive. But on macOS, we must use native traffic lights to get this feature.
|
Yeah! But window controls on windows and linux are way less complicated so you can realistically archive something that feels good on those platforms by using html/css/js |
if want hide toolbar_button and let title transparent , I fix and complete a perfercet solution, thanks @JonasKruckenberg use cocoa::appkit::{NSWindow, NSWindowStyleMask, NSWindowTitleVisibility};
pub trait WindowExt {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool);
}
impl<R: Runtime> WindowExt for Window<R> {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, title_transparent: bool, remove_tool_bar: bool) {
unsafe {
let id = self.ns_window().unwrap() as cocoa::base::id;
NSWindow::setTitlebarAppearsTransparent_(id, cocoa::base::YES);
let mut style_mask = id.styleMask();
style_mask.set(
NSWindowStyleMask::NSFullSizeContentViewWindowMask,
title_transparent,
);
if remove_tool_bar {
style_mask.remove(
NSWindowStyleMask::NSClosableWindowMask
| NSWindowStyleMask::NSMiniaturizableWindowMask
| NSWindowStyleMask::NSResizableWindowMask,
);
}
id.setStyleMask_(style_mask);
id.setTitleVisibility_(if title_transparent {
NSWindowTitleVisibility::NSWindowTitleHidden
} else {
NSWindowTitleVisibility::NSWindowTitleVisible
});
id.setTitlebarAppearsTransparent_(if title_transparent {
cocoa::base::YES
} else {
cocoa::base::NO
});
}
}
} let win = app.get_window("main").unwrap();
win.set_transparent_titlebar(true, false); let win = app.get_window("main").unwrap();
win.set_transparent_titlebar(true, true); |
for removing traffic lights, from previous solution, window will not be resized or minimized manually or from Tauri API I found another method for this (inspired from previous comment) #[cfg(target_os = "macos")]
use cocoa::appkit::{NSWindow, NSWindowButton, NSWindowStyleMask, NSWindowTitleVisibility};
#[cfg(target_os = "macos")]
use objc::runtime::YES;
use tauri::{Runtime, Window};
#[cfg(target_os = "macos")]
#[macro_use]
extern crate objc;
pub trait WindowExt {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool);
}
impl<R: Runtime> WindowExt for Window<R> {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, title_transparent: bool, remove_tool_bar: bool) {
unsafe {
let id = self.ns_window().unwrap() as cocoa::base::id;
NSWindow::setTitlebarAppearsTransparent_(id, cocoa::base::YES);
let mut style_mask = id.styleMask();
style_mask.set(
NSWindowStyleMask::NSFullSizeContentViewWindowMask,
title_transparent,
);
id.setStyleMask_(style_mask);
if remove_tool_bar {
let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton);
let _: () = msg_send![close_button, setHidden: YES];
let min_button = id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton);
let _: () = msg_send![min_button, setHidden: YES];
let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton);
let _: () = msg_send![zoom_button, setHidden: YES];
}
id.setTitleVisibility_(if title_transparent {
NSWindowTitleVisibility::NSWindowTitleHidden
} else {
NSWindowTitleVisibility::NSWindowTitleVisible
});
id.setTitlebarAppearsTransparent_(if title_transparent {
cocoa::base::YES
} else {
cocoa::base::NO
});
}
}
} // see previous comment for usage and result
let win = app.get_window("main").unwrap();
win.set_transparent_titlebar(true, true);
[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.24"
objc = "0.2.7" |
electron/electron#33066 This could serve as a good guide for theming the native windows titlebar, it was implemented in an effort to bring Windows 11 features to the themed titlebar VSCode has. |
@JonasKruckenberg How to change the traffic light position, i found some information, but I don't understand object-c https://github.com/patr0nus/DeskGap/blob/master/lib/src/platform/mac/BrowserWindow.mm#L86 i found answer:
https://github.com/lukakerr/NSWindowStyles#12-transparent-toolbar-without-seperator |
@haasal EDIT: |
Using the code by @haasal from #2663 (comment) works great except if I put any buttons I put inside the (now empty/invisible) titlebar area they are having difficulties getting the click events through. (The solution from #2663 (comment) works perfectly except the traffic lights are in the wrong place as I need a taller titlebar 😅) Is there anything I could change in the titlebar constructor code to allow it to pass all clicks through? |
I see that the issue has been closed because the macOS implementation has been merged. Since Windows 11 also brought more window tiling features into the title bar buttons, it might not be true anymore that HTML/CSS/JS will be enough to recreate a good platform's title bar experience.
I found this article that might be helpful to implement the native custom title bar overlay on windows: https://learn.microsoft.com/en-us/windows/apps/develop/title-bar @lucasfernog Could you consider reopening the issue for windows implementation? |
@shenghan97 That guide doesn't apply to Tauri. From the 2 options, |
Thank you! Good to know that! Although I'm not quite sure if the Full Customization section in the guide is talking about removing the title bar completely with the window buttons. The windows (caption) buttons are still controlled by the system. It says in the guide:
But the guide sadly indeed doesn't seem to apply to win32 applications. |
Thank you for implementing this @probablykasper and thank you @lucasfernog for getting it in. Also thanks to everyone who contributed with their findings and workarounds. I'm sure this issue will still be helpful for those who want more customisation out of their window title bars where configuration doesn't cover it. I think the current change is a good start. I look forward to see more support like Electron window customization and some feature parity between macOS, Windows (and possibly GTK?) |
I have the same situation. Two solutions with two flaws. Anyone with better implementation? |
Try this in
|
Is it actually possible now on macOS to define an inset for the traffic lights via an API or similar, not using that workaround from haasal? |
Nope, the new built-in api does not support customizing the position yet. |
See #4789 |
It's August 2023, is there a solution for Windows now? |
@zjprie094 well at least on Windows 11 there's dark theme titlebars |
The titleBarStyle property work but the window is not movable like it should be. Any solution? |
@microSoftware With a disabled/overlayed titlebar style you now have to use the data-tauri-drag-region attribute to specify html elements that should act as your drag region (note that window.startDragging must be enabled on the allowlist, example: https://tauri.app/v1/guides/features/window-customization#tauriconfjson - it also shows the usage of the attribute itself). It's basically the same as if you disabled decorations as a whole. |
Looks like |
Okay so how do i hide the title bar on windows then? |
Sadly i use tauri 2.0 alpha and so many tauri.conf properties doesn't work like "startDragging" or allowList |
To remove the title bar on windows, I used
|
@microSoftware - I am on the same boat. It is kind of took a good time for me to figure out the 2.0 alpha does not support these settings in tauri.config. Anything you found out to get it work? |
no sorry. |
Is your feature request related to a problem? Please describe.
When creating frameless windows you're required to provide your own UI for window controls. This has multiple problems with consistency and accessibility and requires more work to get close to the UX that is already provided by the native window system.
For example on macOS there are different actions based on how you interact with the window controls ("traffic lights"):
Alt
/Option
key while clicking on "resize" will maximize the window as opposed to the default fullscreen behavior.And many more edge-cases that needs to be handled in order to provide native-like experience.
These cases only describes macOS-specific parts, but could easily apply to Windows and Linux as well, which would require more work to provide native-like UI.
Frameless windows also has several problems as outlined in #2549 and described in Electron's documentation
Describe the solution you'd like
Support the ability to set the titlebar style similarly to Electron's
titleBarStyle
setting which allows for custom title bars while preserving native window controls in different ways.Describe alternatives you've considered
I don't believe there are any alternatives and needs to be solved within Tauri.
The text was updated successfully, but these errors were encountered: