A minimal Tauri plugin for macOS that creates a transparent title bar and adds a custom native button in the title bar region. It also disables dragging the window by the entire background, allowing only the title bar area (or a specific region) to handle window movement.
This plugin demonstrates how to:
- Make the macOS window’s title bar transparent.
- Extend the content view to cover the title bar area.
- Disable automatically dragging the window by the entire background (
[nsWindow setMovableByWindowBackground:NO]).
Note: This plugin is macOS-only. When building on other platforms, the code is conditionally excluded.
-
Add this plugin as a dependency in your Cargo.toml:
[dependencies] # ... native_titlebar_plugin = { path = "path/to/this/plugin" } # or tauri-plugin-native-titlebar = { git = "https://github.com/bookcicle/native-titlebar.git" }
-
Include the build script in your
build.rs(or ensure it’s part of your plugin’s build process). If you’re using the provided examplemain()function as-is, ensure it runs in your build pipeline:// build.rs or main() in the plugin crate #[cfg(target_os = "macos")] println!("cargo:rustc-link-lib=framework=AppKit"); #[cfg(target_os = "macos")] println!("cargo:rustc-link-lib=framework=Foundation"); #[cfg(target_os = "macos")] cc::Build::new() .file("src/native_titlebar.m") .flag("-fobjc-arc") .flag("-mmacosx-version-min=10.11") .compile("native-titlebar");
-
Enable the plugin in your Tauri application by referencing it in your code. Make sure the plugin’s commands are registered and built before your final Tauri build.
-
Register the command: In the plugin code, we define:
const COMMANDS: &[&str] = &["titlebar"];
You should ensure your Tauri application includes this plugin’s command registration, typically via something like:
use tauri::Manager; // ... tauri::Builder::default() .invoke_handler(tauri::generate_handler![titlebar]) // Register the command // ... .run(tauri::generate_context!()) .expect("error while running tauri application");
-
Call the command: From your Tauri frontend (JavaScript/TypeScript), invoke the command:
window.__TAURI__.invoke("titlebar") .then(() => { console.log("Titlebar customized on macOS"); }) .catch((err) => { console.error("Failed to setup titlebar", err); });
On macOS, this will:
- Make the title bar transparent.
- Extend your content view to the top.
- Add a native button at the top-left corner.
- Prevent the entire window background from being used to drag the window (only the title bar region can be used).
-
Title Bar Customization
[nsWindow setTitlebarAppearsTransparent:YES]; nsWindow.styleMask |= NSWindowStyleMaskFullSizeContentView;
This makes the title bar transparent and allows the content view to extend into the title bar region.
-
Disable Full-Window Dragging
[nsWindow setMovableByWindowBackground:NO];
Stops the entire window background from being draggable. By default, macOS would treat the entire extended view as a draggable title bar.
-
Add a Button
NSView *contentView = [nsWindow contentView]; NSRect contentFrame = [contentView frame]; CGFloat buttonWidth = 80.0; CGFloat buttonHeight = 24.0; CGFloat margin = 8.0; // Logic to create and position NSButton (commented in the skeleton).
The code positions a button near the top-left corner of the window. You can adjust dimensions and margins as needed.
-
Button Action
void customButtonPressed(id sender) { NSLog(@"Button Pressed!"); }
Currently, the action just logs a message to the console.
When you call titlebar(), Tauri will pass the native NSWindow pointer (ns_window().unwrap()) to our setup_titlebar_buttons function on macOS. That function applies all the title bar customizations and positions the button.
Because [nsWindow setMovableByWindowBackground:NO] is set, only the standard “title bar” area is draggable. If you have a fully custom layout (for instance, an HTML/CSS interface in your Tauri app), you can specify draggable regions using CSS:
- Make an element draggable:
.titlebar-drag-region { -webkit-app-region: drag; -webkit-user-select: none; }
- Exclude buttons or text from dragging:
.no-drag { -webkit-app-region: no-drag; }
Ensure you position these elements at the top of your app where the title bar would normally be. Otherwise, the user may not be able to move the window at all.
- Button Appearance: You can style the native
NSButton(or substitute anNSViewand handle events yourself). - Window Controls: If you want to reposition or hide the standard macOS traffic-light buttons, see Apple’s NSWindow documentation.
- Platform Compatibility: This code is macOS-specific. On other platforms, the code is conditionally excluded. If you need similar functionality on Windows or Linux, you’ll need platform-specific approaches.
This code is provided as-is. Please adapt, extend, and use in accordance with your project’s needs and licensing requirements.