From 02af143caecc66412134e21dd5c2abd3276cd1d4 Mon Sep 17 00:00:00 2001 From: FabianLars Date: Sun, 12 Jan 2025 13:06:10 +0100 Subject: [PATCH 1/2] moving to macbook --- crates/tauri-cli/config.schema.json | 32 +++++++++++++++++++ crates/tauri-cli/src/helpers/flock.rs | 8 ++--- crates/tauri-runtime-wry/src/lib.rs | 6 ++++ .../schemas/config.schema.json | 32 +++++++++++++++++++ crates/tauri-utils/src/config.rs | 25 +++++++++++++++ 5 files changed, 97 insertions(+), 6 deletions(-) diff --git a/crates/tauri-cli/config.schema.json b/crates/tauri-cli/config.schema.json index 4a804ee4ebc6..69a2a3160bfd 100644 --- a/crates/tauri-cli/config.schema.json +++ b/crates/tauri-cli/config.schema.json @@ -424,6 +424,17 @@ } ] }, + "trafficLightPosition": { + "description": "The position of the window controls on macOS.\n Requires titleBarStyle: Overlay and decorations: true.", + "anyOf": [ + { + "$ref": "#/definitions/LogicalPosition" + }, + { + "type": "null" + } + ] + }, "hiddenTitle": { "description": "If `true`, sets the window title to be hidden on macOS.", "default": false, @@ -584,6 +595,27 @@ } ] }, + "LogicalPosition": { + "description": "Position coordinates struct.", + "type": "object", + "required": [ + "x", + "y" + ], + "properties": { + "x": { + "description": "X coordinate.", + "type": "number", + "format": "double" + }, + "y": { + "description": "Y coordinate.", + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, "WindowEffectsConfig": { "description": "The window effects configuration object", "type": "object", diff --git a/crates/tauri-cli/src/helpers/flock.rs b/crates/tauri-cli/src/helpers/flock.rs index 84ead6ae9170..e55af96afe13 100644 --- a/crates/tauri-cli/src/helpers/flock.rs +++ b/crates/tauri-cli/src/helpers/flock.rs @@ -327,15 +327,11 @@ mod sys { } pub(super) fn error_contended(err: &Error) -> bool { - err - .raw_os_error() - .map_or(false, |x| x == ERROR_LOCK_VIOLATION as i32) + err.raw_os_error() == Some(ERROR_LOCK_VIOLATION as i32) } pub(super) fn error_unsupported(err: &Error) -> bool { - err - .raw_os_error() - .map_or(false, |x| x == ERROR_INVALID_FUNCTION as i32) + err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32) } pub(super) fn unlock(file: &File) -> Result<()> { diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index beaa7f9cb4af..57aac6e031bb 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -1068,6 +1068,12 @@ impl WindowBuilder for WindowBuilderWrapper { self } + #[cfg(target_os = "macos")] + fn traffic_light_position(mut self, position: Position) -> Self { + self.inner = self.inner.with_traffic_light_inset(position); + self + } + #[cfg(target_os = "macos")] fn hidden_title(mut self, hidden: bool) -> Self { self.inner = self.inner.with_title_hidden(hidden); diff --git a/crates/tauri-schema-generator/schemas/config.schema.json b/crates/tauri-schema-generator/schemas/config.schema.json index 4a804ee4ebc6..69a2a3160bfd 100644 --- a/crates/tauri-schema-generator/schemas/config.schema.json +++ b/crates/tauri-schema-generator/schemas/config.schema.json @@ -424,6 +424,17 @@ } ] }, + "trafficLightPosition": { + "description": "The position of the window controls on macOS.\n Requires titleBarStyle: Overlay and decorations: true.", + "anyOf": [ + { + "$ref": "#/definitions/LogicalPosition" + }, + { + "type": "null" + } + ] + }, "hiddenTitle": { "description": "If `true`, sets the window title to be hidden on macOS.", "default": false, @@ -584,6 +595,27 @@ } ] }, + "LogicalPosition": { + "description": "Position coordinates struct.", + "type": "object", + "required": [ + "x", + "y" + ], + "properties": { + "x": { + "description": "X coordinate.", + "type": "number", + "format": "double" + }, + "y": { + "description": "Y coordinate.", + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, "WindowEffectsConfig": { "description": "The window effects configuration object", "type": "object", diff --git a/crates/tauri-utils/src/config.rs b/crates/tauri-utils/src/config.rs index 3877fefeb305..0f25c99e47e7 100644 --- a/crates/tauri-utils/src/config.rs +++ b/crates/tauri-utils/src/config.rs @@ -511,6 +511,17 @@ pub struct Position { pub y: u32, } +/// Position coordinates struct. +#[derive(Default, Debug, PartialEq, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "schema", derive(JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct LogicalPosition { + /// X coordinate. + pub x: f64, + /// Y coordinate. + pub y: f64, +} + /// Size of the window. #[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] #[cfg_attr(feature = "schema", derive(JsonSchema))] @@ -1569,6 +1580,10 @@ pub struct WindowConfig { /// The style of the macOS title bar. #[serde(default, alias = "title-bar-style")] pub title_bar_style: TitleBarStyle, + /// The position of the window controls on macOS. + /// Requires titleBarStyle: Overlay and decorations: true. + #[serde(default, alias = "traffic-light-position")] + pub traffic_light_position: Option, /// If `true`, sets the window title to be hidden on macOS. #[serde(default, alias = "hidden-title")] pub hidden_title: bool, @@ -1725,6 +1740,7 @@ impl Default for WindowConfig { window_classname: None, theme: None, title_bar_style: Default::default(), + traffic_light_position: None, hidden_title: false, accept_first_mouse: false, tabbing_identifier: None, @@ -2905,6 +2921,13 @@ mod build { } } + impl ToTokens for LogicalPosition { + fn to_tokens(&self, tokens: &mut TokenStream) { + let LogicalPosition { x, y } = self; + literal_struct!(tokens, ::tauri::utils::config::LogicalPosition, x, y) + } + } + impl ToTokens for crate::WindowEffect { fn to_tokens(&self, tokens: &mut TokenStream) { let prefix = quote! { ::tauri::utils::WindowEffect }; @@ -2991,6 +3014,7 @@ mod build { let window_classname = opt_str_lit(self.window_classname.as_ref()); let theme = opt_lit(self.theme.as_ref()); let title_bar_style = &self.title_bar_style; + let traffic_light_position = opt_lit(self.traffic_light_position.as_ref()); let hidden_title = self.hidden_title; let accept_first_mouse = self.accept_first_mouse; let tabbing_identifier = opt_str_lit(self.tabbing_identifier.as_ref()); @@ -3042,6 +3066,7 @@ mod build { window_classname, theme, title_bar_style, + traffic_light_position, hidden_title, accept_first_mouse, tabbing_identifier, From ba941fa6038c5e040ef62c6c2989dbe029fac30a Mon Sep 17 00:00:00 2001 From: fabianlars Date: Sun, 12 Jan 2025 15:13:54 +0100 Subject: [PATCH 2/2] that was so weird to implement --- Cargo.lock | 34 ++++++++++++------- Cargo.toml | 2 ++ crates/tauri-cli/config.schema.json | 2 +- crates/tauri-runtime-wry/src/lib.rs | 32 +++++++++++++++-- crates/tauri-runtime/src/lib.rs | 11 +++++- crates/tauri-runtime/src/webview.rs | 22 ++++++++++++ crates/tauri-runtime/src/window.rs | 7 ++++ .../schemas/config.schema.json | 2 +- crates/tauri-utils/src/config.rs | 1 + crates/tauri/src/test/mock_runtime.rs | 9 +++++ examples/helloworld/tauri.conf.json | 4 ++- 11 files changed, 107 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36696a0f6fab..2db5f586b11d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1775,7 +1775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2830,7 +2830,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -6347,7 +6347,7 @@ dependencies = [ "aes-gcm", "aes-kw", "argon2", - "base64 0.22.1", + "base64 0.21.7", "bitfield", "block-padding", "blowfish", @@ -6937,7 +6937,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -7627,7 +7627,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -8939,8 +8939,7 @@ dependencies = [ [[package]] name = "tao" version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3731d04d4ac210cd5f344087733943b9bfb1a32654387dad4d1c70de21aee2c9" +source = "git+https://github.com/tauri-apps/tao#cdfba4ecfcf34b81b3cc13ba53d6b42c9d0b6259" dependencies = [ "bitflags 2.7.0", "cocoa", @@ -8965,7 +8964,7 @@ dependencies = [ "parking_lot", "raw-window-handle", "scopeguard", - "tao-macros", + "tao-macros 0.1.3 (git+https://github.com/tauri-apps/tao)", "unicode-segmentation", "url", "windows", @@ -8985,6 +8984,16 @@ dependencies = [ "syn 2.0.95", ] +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "git+https://github.com/tauri-apps/tao#cdfba4ecfcf34b81b3cc13ba53d6b42c9d0b6259" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "tap" version = "1.0.1" @@ -9593,7 +9602,7 @@ dependencies = [ "getrandom 0.2.15", "once_cell", "rustix 0.38.43", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -10845,7 +10854,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -11402,8 +11411,7 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "wry" version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e644bf458e27b11b0ecafc9e5633d1304fdae82baca1d42185669752fe6ca4f" +source = "git+https://github.com/tauri-apps/wry#26abf63d79c4a0fcff8ea39d0ff677686f5b546c" dependencies = [ "base64 0.22.1", "block2", @@ -11430,7 +11438,7 @@ dependencies = [ "raw-window-handle", "sha2", "soup3", - "tao-macros", + "tao-macros 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.10", "tracing", "url", diff --git a/Cargo.toml b/Cargo.toml index 963894b5910b..0c00ffe4c826 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,3 +70,5 @@ opt-level = "s" [patch.crates-io] schemars_derive = { git = 'https://github.com/tauri-apps/schemars.git', branch = 'feat/preserve-description-newlines' } tauri = { path = "./crates/tauri" } +wry = { git = "https://github.com/tauri-apps/wry" } +tao = { git = "https://github.com/tauri-apps/tao" } diff --git a/crates/tauri-cli/config.schema.json b/crates/tauri-cli/config.schema.json index 69a2a3160bfd..462cc7e9c0b0 100644 --- a/crates/tauri-cli/config.schema.json +++ b/crates/tauri-cli/config.schema.json @@ -425,7 +425,7 @@ ] }, "trafficLightPosition": { - "description": "The position of the window controls on macOS.\n Requires titleBarStyle: Overlay and decorations: true.", + "description": "The position of the window controls on macOS.\n\n Requires titleBarStyle: Overlay and decorations: true.", "anyOf": [ { "$ref": "#/definitions/LogicalPosition" diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index 57aac6e031bb..20e1248b1121 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -787,6 +787,9 @@ impl WindowBuilder for WindowBuilderWrapper { if let Some(identifier) = &config.tabbing_identifier { window = window.tabbing_identifier(identifier); } + if let Some(position) = &config.traffic_light_position { + window = window.traffic_light_position(position.x, position.y); + } } #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] @@ -1069,8 +1072,10 @@ impl WindowBuilder for WindowBuilderWrapper { } #[cfg(target_os = "macos")] - fn traffic_light_position(mut self, position: Position) -> Self { - self.inner = self.inner.with_traffic_light_inset(position); + fn traffic_light_position(mut self, x: f64, y: f64) -> Self { + self.inner = self + .inner + .with_traffic_light_inset(TaoLogicalPosition::new(x, y)); self } @@ -1276,6 +1281,7 @@ pub enum WindowMessage { SetOverlayIcon(Option), SetProgressBar(ProgressBarState), SetTitleBarStyle(tauri_utils::TitleBarStyle), + SetTrafficLightPosition(Position), SetTheme(Option), SetBackgroundColor(Option), DragWindow, @@ -2179,6 +2185,16 @@ impl WindowDispatch for WryWindowDispatcher { ) } + fn set_traffic_light_position(&self, position: Position) -> Result<()> { + send_user_message( + &self.context, + Message::Window( + self.window_id, + WindowMessage::SetTrafficLightPosition(position), + ), + ) + } + fn set_theme(&self, theme: Option) -> Result<()> { send_user_message( &self.context, @@ -3186,6 +3202,10 @@ fn handle_user_message( } }; } + WindowMessage::SetTrafficLightPosition(_position) => { + #[cfg(target_os = "macos")] + window.set_traffic_light_inset(_position); + } WindowMessage::SetTheme(theme) => { window.set_theme(match theme { Some(Theme::Light) => Some(TaoTheme::Light), @@ -4366,6 +4386,14 @@ fn create_webview( } } + #[cfg(target_os = "macos")] + { + use wry::WebViewBuilderExtDarwin; + if let Some(position) = &webview_attributes.traffic_light_position { + webview_builder = webview_builder.with_traffic_light_inset(*position); + } + } + webview_builder = webview_builder.with_ipc_handler(create_ipc_handler( kind, window_id.clone(), diff --git a/crates/tauri-runtime/src/lib.rs b/crates/tauri-runtime/src/lib.rs index 8c93a19a0907..7115c0bedc14 100644 --- a/crates/tauri-runtime/src/lib.rs +++ b/crates/tauri-runtime/src/lib.rs @@ -235,7 +235,7 @@ pub enum RunEvent { Resumed, /// Emitted when all of the event loop's input events have been processed and redraw processing is about to begin. /// - /// This event is useful as a place to put your code that should be run after all state-changing events have been handled and you want to do stuff (updating state, performing calculations, etc) that happens as the “main body” of your event loop. + /// This event is useful as a place to put your code that should be run after all state-changing events have been handled and you want to do stuff (updating state, performing calculations, etc) that happens as the "main body" of your event loop. MainEventsCleared, /// Emitted when the user wants to open the specified resource with the app. #[cfg(any(target_os = "macos", target_os = "ios"))] @@ -847,6 +847,15 @@ pub trait WindowDispatch: Debug + Clone + Send + Sync + Sized + 's /// - **Linux / Windows / iOS / Android:** Unsupported. fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()>; + /// Change the position of the window controls. Available on macOS only. + /// + /// Requires titleBarStyle: Overlay and decorations: true. + /// + /// ## Platform-specific + /// + /// - **Linux / Windows / iOS / Android:** Unsupported. + fn set_traffic_light_position(&self, position: Position) -> Result<()>; + /// Sets the theme for this window. /// /// ## Platform-specific diff --git a/crates/tauri-runtime/src/webview.rs b/crates/tauri-runtime/src/webview.rs index f317a5857638..24b6f2ea24ee 100644 --- a/crates/tauri-runtime/src/webview.rs +++ b/crates/tauri-runtime/src/webview.rs @@ -215,6 +215,7 @@ pub struct WebviewAttributes { pub use_https_scheme: bool, pub devtools: Option, pub background_color: Option, + pub traffic_light_position: Option, } impl From<&WindowConfig> for WebviewAttributes { @@ -230,6 +231,13 @@ impl From<&WindowConfig> for WebviewAttributes { { builder = builder.transparent(config.transparent); } + #[cfg(target_os = "macos")] + { + if let Some(position) = &config.traffic_light_position { + builder = + builder.traffic_light_position(dpi::LogicalPosition::new(position.x, position.y).into()); + } + } builder = builder.accept_first_mouse(config.accept_first_mouse); if !config.drag_drop_enabled { builder = builder.disable_drag_drop_handler(); @@ -279,6 +287,7 @@ impl WebviewAttributes { use_https_scheme: false, devtools: None, background_color: None, + traffic_light_position: None, } } @@ -444,6 +453,19 @@ impl WebviewAttributes { self.background_color = Some(color); self } + + /// Change the position of the window controls. Available on macOS only. + /// + /// Requires titleBarStyle: Overlay and decorations: true. + /// + /// ## Platform-specific + /// + /// - **Linux / Windows / iOS / Android:** Unsupported. + #[must_use] + pub fn traffic_light_position(mut self, position: dpi::Position) -> Self { + self.traffic_light_position = Some(position); + self + } } /// IPC handler. diff --git a/crates/tauri-runtime/src/window.rs b/crates/tauri-runtime/src/window.rs index dc843100da98..0d69bca9cfba 100644 --- a/crates/tauri-runtime/src/window.rs +++ b/crates/tauri-runtime/src/window.rs @@ -423,6 +423,13 @@ pub trait WindowBuilder: WindowBuilderBase { #[must_use] fn title_bar_style(self, style: tauri_utils::TitleBarStyle) -> Self; + /// Change the position of the window controls on macOS. + /// + /// Requires titleBarStyle: Overlay and decorations: true. + #[cfg(target_os = "macos")] + #[must_use] + fn traffic_light_position(self, x: f64, y: f64) -> Self; + /// Hide the window title. #[cfg(target_os = "macos")] #[must_use] diff --git a/crates/tauri-schema-generator/schemas/config.schema.json b/crates/tauri-schema-generator/schemas/config.schema.json index 69a2a3160bfd..462cc7e9c0b0 100644 --- a/crates/tauri-schema-generator/schemas/config.schema.json +++ b/crates/tauri-schema-generator/schemas/config.schema.json @@ -425,7 +425,7 @@ ] }, "trafficLightPosition": { - "description": "The position of the window controls on macOS.\n Requires titleBarStyle: Overlay and decorations: true.", + "description": "The position of the window controls on macOS.\n\n Requires titleBarStyle: Overlay and decorations: true.", "anyOf": [ { "$ref": "#/definitions/LogicalPosition" diff --git a/crates/tauri-utils/src/config.rs b/crates/tauri-utils/src/config.rs index 0f25c99e47e7..7b791c031918 100644 --- a/crates/tauri-utils/src/config.rs +++ b/crates/tauri-utils/src/config.rs @@ -1581,6 +1581,7 @@ pub struct WindowConfig { #[serde(default, alias = "title-bar-style")] pub title_bar_style: TitleBarStyle, /// The position of the window controls on macOS. + /// /// Requires titleBarStyle: Overlay and decorations: true. #[serde(default, alias = "traffic-light-position")] pub traffic_light_position: Option, diff --git a/crates/tauri/src/test/mock_runtime.rs b/crates/tauri/src/test/mock_runtime.rs index 2d45794762ca..60e075b45384 100644 --- a/crates/tauri/src/test/mock_runtime.rs +++ b/crates/tauri/src/test/mock_runtime.rs @@ -465,6 +465,11 @@ impl WindowBuilder for MockWindowBuilder { self } + #[cfg(target_os = "macos")] + fn traffic_light_position(self, x: f64, y: f64) -> Self { + self + } + #[cfg(target_os = "macos")] fn hidden_title(self, transparent: bool) -> Self { self @@ -993,6 +998,10 @@ impl WindowDispatch for MockWindowDispatcher { Ok(()) } + fn set_traffic_light_position(&self, position: Position) -> Result<()> { + Ok(()) + } + fn set_size_constraints( &self, constraints: tauri_runtime::window::WindowSizeConstraints, diff --git a/examples/helloworld/tauri.conf.json b/examples/helloworld/tauri.conf.json index 5b6d19585f8d..89ca17569baa 100644 --- a/examples/helloworld/tauri.conf.json +++ b/examples/helloworld/tauri.conf.json @@ -14,7 +14,9 @@ "width": 800, "height": 600, "resizable": true, - "fullscreen": false + "fullscreen": false, + "titleBarStyle": "Overlay", + "trafficLightPosition": { "x": 100, "y": 100 } } ], "security": {