Skip to content

Commit

Permalink
feat(macos): title_bar_style and hidden_title window options, closes
Browse files Browse the repository at this point in the history
 #2663 (#3965)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
  • Loading branch information
probablykasper and lucasfernog authored Sep 30, 2022
1 parent 39443b4 commit 321f3fe
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 5 deletions.
6 changes: 6 additions & 0 deletions .changes/hidden-title-macos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'tauri': minor
"tauri-runtime-wry": minor
---

Add `hidden_title` option for macOS windows.
6 changes: 6 additions & 0 deletions .changes/transparent-titlebar-macos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'tauri': minor
"tauri-runtime-wry": minor
---

Add `title_bar_style` option for macOS windows.
39 changes: 35 additions & 4 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ use wry::application::platform::unix::{WindowBuilderExtUnix, WindowExtUnix};
#[cfg(windows)]
use wry::application::platform::windows::{WindowBuilderExtWindows, WindowExtWindows};

#[cfg(target_os = "macos")]
use tauri_utils::TitleBarStyle;
use tauri_utils::{config::WindowConfig, debug_eprintln, Theme};
use uuid::Uuid;
use wry::{
Expand Down Expand Up @@ -739,6 +741,13 @@ impl WindowBuilder for WindowBuilderWrapper {
.skip_taskbar(config.skip_taskbar)
.theme(config.theme);

#[cfg(target_os = "macos")]
{
window = window
.hidden_title(config.hidden_title)
.title_bar_style(config.title_bar_style);
}

#[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
{
window = window.transparent(config.transparent);
Expand Down Expand Up @@ -879,6 +888,32 @@ impl WindowBuilder for WindowBuilderWrapper {
self
}

#[cfg(target_os = "macos")]
fn title_bar_style(mut self, style: TitleBarStyle) -> Self {
match style {
TitleBarStyle::Visible => {
self.inner = self.inner.with_titlebar_transparent(false);
// Fixes rendering issue when resizing window with devtools open (https://github.com/tauri-apps/tauri/issues/3914)
self.inner = self.inner.with_fullsize_content_view(true);
}
TitleBarStyle::Transparent => {
self.inner = self.inner.with_titlebar_transparent(true);
self.inner = self.inner.with_fullsize_content_view(false);
}
TitleBarStyle::Overlay => {
self.inner = self.inner.with_titlebar_transparent(true);
self.inner = self.inner.with_fullsize_content_view(true);
}
}
self
}

#[cfg(target_os = "macos")]
fn hidden_title(mut self, hidden: bool) -> Self {
self.inner = self.inner.with_title_hidden(hidden);
self
}

fn icon(mut self, icon: Icon) -> Result<Self> {
self.inner = self
.inner
Expand Down Expand Up @@ -2878,10 +2913,6 @@ fn create_webview<T: UserEvent>(

let window_event_listeners = WindowEventListeners::default();

#[cfg(target_os = "macos")]
{
window_builder.inner = window_builder.inner.with_fullsize_content_view(true);
}
#[cfg(windows)]
{
window_builder.inner = window_builder
Expand Down
12 changes: 12 additions & 0 deletions core/tauri-runtime/src/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use crate::{menu::Menu, window::DetachedWindow, Icon};

#[cfg(target_os = "macos")]
use tauri_utils::TitleBarStyle;
use tauri_utils::{
config::{WindowConfig, WindowUrl},
Theme,
Expand Down Expand Up @@ -189,6 +191,16 @@ pub trait WindowBuilder: WindowBuilderBase {
#[must_use]
fn owner_window(self, owner: HWND) -> Self;

/// Hide the titlebar. Titlebar buttons will still be visible.
#[cfg(target_os = "macos")]
#[must_use]
fn title_bar_style(self, style: TitleBarStyle) -> Self;

/// Hide the window title.
#[cfg(target_os = "macos")]
#[must_use]
fn hidden_title(self, hidden: bool) -> Self;

/// Forces a theme or uses the system settings if None was provided.
fn theme(self, theme: Option<Theme>) -> Self;

Expand Down
28 changes: 27 additions & 1 deletion core/tauri-utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ use std::{
/// Items to help with parsing content into a [`Config`].
pub mod parse;

use crate::TitleBarStyle;

pub use self::parse::parse;

/// An URL to open on a Tauri webview window.
Expand Down Expand Up @@ -859,6 +861,12 @@ pub struct WindowConfig {
pub skip_taskbar: bool,
/// The initial window theme. Defaults to the system theme. Only implemented on Windows and macOS 10.14+.
pub theme: Option<crate::Theme>,
/// The style of the macOS title bar.
#[serde(default, alias = "title-bar-style")]
pub title_bar_style: TitleBarStyle,
/// If `true`, sets the window title to be hidden on macOS.
#[serde(default, alias = "hidden-title")]
pub hidden_title: bool,
}

impl Default for WindowConfig {
Expand Down Expand Up @@ -887,6 +895,8 @@ impl Default for WindowConfig {
always_on_top: false,
skip_taskbar: false,
theme: None,
title_bar_style: Default::default(),
hidden_title: false,
}
}
}
Expand Down Expand Up @@ -2934,6 +2944,18 @@ mod build {
}
}

impl ToTokens for crate::TitleBarStyle {
fn to_tokens(&self, tokens: &mut TokenStream) {
let prefix = quote! { ::tauri::utils::TitleBarStyle };

tokens.append_all(match self {
Self::Visible => quote! { #prefix::Visible },
Self::Transparent => quote! { #prefix::Transparent },
Self::Overlay => quote! { #prefix::Overlay },
})
}
}

impl ToTokens for WindowConfig {
fn to_tokens(&self, tokens: &mut TokenStream) {
let label = str_lit(&self.label);
Expand All @@ -2959,6 +2981,8 @@ mod build {
let always_on_top = self.always_on_top;
let skip_taskbar = self.skip_taskbar;
let theme = opt_lit(self.theme.as_ref());
let title_bar_style = &self.title_bar_style;
let hidden_title = self.hidden_title;

literal_struct!(
tokens,
Expand All @@ -2985,7 +3009,9 @@ mod build {
decorations,
always_on_top,
skip_taskbar,
theme
theme,
title_bar_style,
hidden_title
);
}
}
Expand Down
62 changes: 62 additions & 0 deletions core/tauri-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,68 @@ impl PackageInfo {
}
}

/// How the window title bar should be displayed.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum TitleBarStyle {
/// A normal title bar.
Visible,
/// Makes the title bar transparent, so the window background color is shown instead.
///
/// Useful if you don't need to have actual HTML under the title bar. This lets you avoid the caveats of using `TitleBarStyle::Overlay`. Will be more useful when Tauri lets you set a custom window background color.
Transparent,
/// Shows the title bar as a transparent overlay over the window's content.
///
/// Keep in mind:
/// - The height of the title bar is different on different OS versions, which can lead to window the controls and title not being where you don't expect.
/// - You need to define a custom drag region to make your window draggable, however due to a limitation you can't drag the window when it's not in focus (https://github.com/tauri-apps/tauri/issues/4316).
/// - The color of the window title depends on the system theme.
Overlay,
}

impl Default for TitleBarStyle {
fn default() -> Self {
Self::Visible
}
}

impl Serialize for TitleBarStyle {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_ref())
}
}

impl<'de> Deserialize<'de> for TitleBarStyle {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Ok(match s.to_lowercase().as_str() {
"transparent" => Self::Transparent,
"overlay" => Self::Overlay,
_ => Self::Visible,
})
}
}

impl Display for TitleBarStyle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Visible => "Visible",
Self::Transparent => "Transparent",
Self::Overlay => "Overlay",
}
)
}
}

/// System theme.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
Expand Down
2 changes: 2 additions & 0 deletions core/tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ pub use runtime::http;
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
pub use runtime::{menu::NativeImage, ActivationPolicy};

#[cfg(target_os = "macos")]
pub use self::utils::TitleBarStyle;
#[cfg(all(desktop, feature = "system-tray"))]
#[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
pub use {
Expand Down
12 changes: 12 additions & 0 deletions core/tauri/src/test/mock_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use tauri_runtime::{
menu::{SystemTrayMenu, TrayHandle},
SystemTray, SystemTrayEvent, TrayId,
};
#[cfg(target_os = "macos")]
use tauri_utils::TitleBarStyle;
use tauri_utils::{config::WindowConfig, Theme};
use uuid::Uuid;

Expand Down Expand Up @@ -259,6 +261,16 @@ impl WindowBuilder for MockWindowBuilder {
self
}

#[cfg(target_os = "macos")]
fn title_bar_style(self, style: TitleBarStyle) -> Self {
self
}

#[cfg(target_os = "macos")]
fn hidden_title(self, transparent: bool) -> Self {
self
}

fn theme(self, theme: Option<Theme>) -> Self {
self
}
Expand Down
18 changes: 18 additions & 0 deletions core/tauri/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub(crate) mod menu;

pub use menu::{MenuEvent, MenuHandle};

#[cfg(target_os = "macos")]
use crate::TitleBarStyle;
use crate::{
app::AppHandle,
command::{CommandArg, CommandItem},
Expand Down Expand Up @@ -433,6 +435,22 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
self
}

/// Sets the [`TitleBarStyle`].
#[cfg(target_os = "macos")]
#[must_use]
pub fn title_bar_style(mut self, style: TitleBarStyle) -> Self {
self.window_builder = self.window_builder.title_bar_style(style);
self
}

/// Hide the window title.
#[cfg(target_os = "macos")]
#[must_use]
pub fn hidden_title(mut self, hidden: bool) -> Self {
self.window_builder = self.window_builder.hidden_title(hidden);
self
}

// ------------------------------------------- Webview attributes -------------------------------------------

/// Adds the provided JavaScript to a list of scripts that should be run after the global object has been created,
Expand Down
9 changes: 9 additions & 0 deletions tooling/api/src/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import { emit, Event, listen, once } from './helpers/event'
import { TauriEvent } from './event'

type Theme = 'light' | 'dark'
type TitleBarStyle = 'visible' | 'transparent' | 'overlay'

/**
* Allows you to retrieve information about a given monitor.
Expand Down Expand Up @@ -2033,6 +2034,14 @@ interface WindowOptions {
* Only implemented on Windows and macOS 10.14+.
*/
theme?: Theme
/**
* The style of the macOS title bar.
*/
titleBarStyle?: TitleBarStyle
/**
* If `true`, sets the window title to be hidden on macOS.
*/
hiddenTitle?: boolean
}

function mapMonitor(m: Monitor | null): Monitor | null {
Expand Down
23 changes: 23 additions & 0 deletions tooling/cli/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,20 @@
"type": "null"
}
]
},
"titleBarStyle": {
"description": "The style of the macOS title bar.",
"default": "Visible",
"allOf": [
{
"$ref": "#/definitions/TitleBarStyle"
}
]
},
"hiddenTitle": {
"description": "Sets the window title to be hidden on macOS.",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
Expand All @@ -665,6 +679,15 @@
"Dark"
]
},
"TitleBarStyle": {
"description": "How the window title bar should be displayed.",
"type": "string",
"enum": [
"Visible",
"Transparent",
"Overlay"
]
},
"CliConfig": {
"description": "describes a CLI configuration",
"type": "object",
Expand Down

0 comments on commit 321f3fe

Please sign in to comment.