From 2a3c3406fc51d6bb975242eb1027eaabb93a6811 Mon Sep 17 00:00:00 2001 From: Corbin Crutchley Date: Fri, 13 Dec 2024 10:21:24 -0800 Subject: [PATCH] chore: fix windowing behavior --- src-tauri/Cargo.lock | 249 +++++++++++++++++--- src-tauri/Cargo.toml | 6 +- src-tauri/capabilities/default.json | 12 +- src-tauri/src/lib.rs | 58 ++--- src-tauri/src/mac/mod.rs | 1 - src-tauri/src/mac/window.rs | 343 ---------------------------- src-tauri/tauri.conf.json | 15 +- src/index.html | 1 + 8 files changed, 268 insertions(+), 417 deletions(-) delete mode 100644 src-tauri/src/mac/mod.rs delete mode 100644 src-tauri/src/mac/window.rs diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4b3c63b..cdf3fce 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -17,6 +17,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "ahash" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0453232ace82dee0dd0b4c87a59bd90f7b53b314f3e0f61fe2ee7c8a16482289" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -590,6 +596,22 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation 0.1.2", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "foreign-types", + "libc", + "objc", +] + [[package]] name = "cocoa" version = "0.26.0" @@ -598,14 +620,28 @@ checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" dependencies = [ "bitflags 2.6.0", "block", - "cocoa-foundation", - "core-foundation", - "core-graphics", + "cocoa-foundation 0.2.0", + "core-foundation 0.10.0", + "core-graphics 0.24.0", "foreign-types", "libc", "objc", ] +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "libc", + "objc", +] + [[package]] name = "cocoa-foundation" version = "0.2.0" @@ -614,8 +650,8 @@ checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" dependencies = [ "bitflags 2.6.0", "block", - "core-foundation", - "core-graphics-types", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", "libc", "objc", ] @@ -655,6 +691,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation" version = "0.10.0" @@ -671,6 +717,19 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + [[package]] name = "core-graphics" version = "0.24.0" @@ -678,12 +737,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ "bitflags 2.6.0", - "core-foundation", - "core-graphics-types", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", "foreign-types", "libc", ] +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.2.0" @@ -691,7 +761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.10.0", "libc", ] @@ -973,6 +1043,15 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "dlv-list" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68df3f2b690c1b86e65ef7830956aededf3cb0a16f898f79b9a6f421a7b6211b" +dependencies = [ + "rand 0.8.5", +] + [[package]] name = "downcast-rs" version = "1.2.1" @@ -1056,6 +1135,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +[[package]] +name = "enigo" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "802e4b2ae123615659085369b453cba87c5562e46ed8050a909fee18a9bc3157" +dependencies = [ + "core-graphics 0.23.2", + "libc", + "objc", + "pkg-config", + "windows 0.51.1", +] + [[package]] name = "enumflags2" version = "0.7.10" @@ -1155,6 +1247,15 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "file-locker" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c3e69656680c6c3d76750b46dfa64bf07626bd2130c540d6cf2d306ba595a8" +dependencies = [ + "nix 0.29.0", +] + [[package]] name = "flate2" version = "1.0.35" @@ -1207,6 +1308,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "freedesktop_entry_parser" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db9c27b72f19a99a895f8ca89e2d26e4ef31013376e56fdafef697627306c3e4" +dependencies = [ + "nom", + "thiserror 1.0.69", +] + [[package]] name = "futf" version = "0.1.5" @@ -1596,6 +1707,15 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1632,15 +1752,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hex_color" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37f101bf4c633f7ca2e4b5e136050314503dd198e78e325ea602c327c484ef0" -dependencies = [ - "rand 0.8.5", -] - [[package]] name = "hound" version = "3.5.1" @@ -2190,6 +2301,29 @@ dependencies = [ "libc", ] +[[package]] +name = "linicon" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee8c5653188a809616c97296180a0547a61dba205bcdcbdd261dbd022a25fd9" +dependencies = [ + "file-locker", + "freedesktop_entry_parser", + "linicon-theme", + "memmap2", + "thiserror 1.0.69", +] + +[[package]] +name = "linicon-theme" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f8240c33bb08c5d8b8cdea87b683b05e61037aa76ff26bef40672cc6ecbb80" +dependencies = [ + "freedesktop_entry_parser", + "rust-ini", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2268,6 +2402,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.9.1" @@ -2314,16 +2457,14 @@ dependencies = [ name = "moonsound" version = "0.1.0" dependencies = [ - "cocoa", - "hex_color", - "objc", - "rand 0.8.5", + "cocoa 0.26.0", "rodio", "serde", "serde_json", "symphonia", "tauri", "tauri-build", + "tauri-plugin-decorum", "tauri-plugin-dialog", "tauri-plugin-opener", "tauri-plugin-window-state", @@ -2789,6 +2930,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-multimap" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c672c7ad9ec066e428c00eb917124a06f08db19e2584de982cc34b1f4c12485" +dependencies = [ + "dlv-list", + "hashbrown 0.9.1", +] + [[package]] name = "ordered-stream" version = "0.2.0" @@ -3393,6 +3544,16 @@ dependencies = [ "symphonia", ] +[[package]] +name = "rust-ini" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63471c4aa97a1cf8332a5f97709a79a4234698de6a1f5087faf66f2dae810e22" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -3740,7 +3901,7 @@ checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" dependencies = [ "bytemuck", "cfg_aliases", - "core-graphics", + "core-graphics 0.24.0", "foreign-types", "js-sys", "log", @@ -4069,9 +4230,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" dependencies = [ "bitflags 2.6.0", - "cocoa", - "core-foundation", - "core-graphics", + "cocoa 0.26.0", + "core-foundation 0.10.0", + "core-graphics 0.24.0", "crossbeam-channel", "dispatch", "dlopen2", @@ -4248,6 +4409,23 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-decorum" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db925c61a04a937028bc91ad8ae64a93b84a1715b964530925a54e793d494999" +dependencies = [ + "anyhow", + "cocoa 0.25.0", + "enigo", + "linicon", + "objc", + "rand 0.8.5", + "serde", + "tauri", + "tauri-plugin", +] + [[package]] name = "tauri-plugin-dialog" version = "2.2.0" @@ -4687,7 +4865,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48a05076dd272615d03033bf04f480199f7d1b66a8ac64d75c625fc4a70c06b" dependencies = [ - "core-graphics", + "core-graphics 0.24.0", "crossbeam-channel", "dirs", "libappindicator", @@ -5174,6 +5352,16 @@ dependencies = [ "windows-version", ] +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core 0.51.1", + "windows-targets 0.48.5", +] + [[package]] name = "windows" version = "0.54.0" @@ -5194,6 +5382,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a662540..09d1905 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] tauri-build = { version = "2", features = [] } [dependencies] -tauri = { version = "2", features = ["macos-private-api"] } +tauri = { version = "2", features = [] } tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" @@ -26,10 +26,8 @@ symphonia = { version = "0.5.3", features = ["mp3"] } tauri-plugin-dialog = "2" rodio = {version = "0.20.1", features = ["symphonia-all"] } window-vibrancy = "0.5.2" -objc = "0.2.7" -hex_color = "3.0.0" tauri-plugin-window-state = "2.2.0" -rand = "0.8.5" +tauri-plugin-decorum = "1.1.1" [target."cfg(target_os = \"macos\")".dependencies] cocoa = "0.26" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 3c1ad59..b6c26a3 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -8,6 +8,16 @@ "permissions": [ "core:default", "opener:default", - "dialog:default" + "dialog:default", + "core:window:allow-close", + "core:window:allow-center", + "core:window:allow-minimize", + "core:window:allow-maximize", + "core:window:allow-set-size", + "core:window:allow-set-focus", + "core:window:allow-is-maximized", + "core:window:allow-start-dragging", + "core:window:allow-toggle-maximize", + "decorum:allow-show-snap-overlay" ] } \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index bb5cfc2..b82f187 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,22 +1,8 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -#[cfg(target_os = "macos")] -#[macro_use] -extern crate cocoa; - -#[cfg(target_os = "macos")] -extern crate objc; - -#[cfg(target_os = "macos")] -mod mac; - -#[cfg(target_os = "windows")] -mod win; - use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink}; use serde::Serialize; -use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial}; use std::fs::File; use std::io::BufReader; use std::path::Path; @@ -25,7 +11,9 @@ use symphonia::core::formats::FormatOptions; use symphonia::core::io::MediaSourceStream; use symphonia::core::meta::MetadataOptions; use symphonia::core::probe::Hint; -use tauri::{AppHandle, Emitter, Manager, State, TitleBarStyle, WebviewUrl, WebviewWindowBuilder}; +use tauri::{AppHandle, Emitter, Manager, State}; +use tauri_plugin_decorum::WebviewWindowExt; +use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial}; thread_local! { static AUDIO: (OutputStream, OutputStreamHandle) = OutputStream::try_default().unwrap(); @@ -170,42 +158,32 @@ fn get_position() -> std::time::Duration { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_window_state::Builder::default().build()) + .plugin(tauri_plugin_decorum::init()) // initialize the decorum plugin .setup(|app| { app.manage(Mutex::new(AppData::default())); - let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) - .title("Transparent Titlebar Window") - .inner_size(800.0, 600.0) - .transparent(true); - - #[cfg(target_os = "macos")] - let win_builder = win_builder.title_bar_style(TitleBarStyle::Transparent); - - let window: tauri::WebviewWindow = win_builder.build().unwrap(); - + // Create a custom titlebar for main window + // On Windows this hides decoration and creates custom window controls + // On macOS it needs hiddenTitle: true and titleBarStyle: overlay + let main_window = app.get_webview_window("main").unwrap(); + main_window.create_overlay_titlebar().unwrap(); if cfg!(target_os = "macos") { - #[cfg(target_os = "macos")] - apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, None) - .expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS"); - - #[cfg(target_os = "macos")] - use mac::window::setup_traffic_light_positioner; + main_window.set_traffic_lights_inset(12.0, 16.0).unwrap(); + main_window.make_transparent().unwrap(); #[cfg(target_os = "macos")] - setup_traffic_light_positioner(window); + apply_vibrancy(&main_window, NSVisualEffectMaterial::HudWindow, None, None) + .expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS"); } else if cfg!(target_os = "windows") { - // #[cfg(target_os = "windows")] - // use win::window::setup_win_window; - - // #[cfg(target_os = "windows")] - // setup_win_window(app); + #[cfg(target_os = "windows")] + apply_blur(&main_window, Some((18, 18, 18, 125))).expect("Unsupported platform! 'apply_blur' is only supported on Windows"); } Ok(()) }) - .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_opener::init()) - .plugin(tauri_plugin_window_state::Builder::default().build()) .invoke_handler(tauri::generate_handler![ read_mp3_metadata, play, diff --git a/src-tauri/src/mac/mod.rs b/src-tauri/src/mac/mod.rs deleted file mode 100644 index d42d7db..0000000 --- a/src-tauri/src/mac/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod window; \ No newline at end of file diff --git a/src-tauri/src/mac/window.rs b/src-tauri/src/mac/window.rs deleted file mode 100644 index 7f9727e..0000000 --- a/src-tauri/src/mac/window.rs +++ /dev/null @@ -1,343 +0,0 @@ -use objc::{msg_send, sel, sel_impl}; -use rand::{distributions::Alphanumeric, Rng}; -use tauri::{Emitter, Runtime, WebviewWindow}; - -const WINDOW_CONTROL_PAD_X: f64 = 15.0; -const WINDOW_CONTROL_PAD_Y: f64 = 23.0; - -struct UnsafeWindowHandle(*mut std::ffi::c_void); -unsafe impl Send for UnsafeWindowHandle {} -unsafe impl Sync for UnsafeWindowHandle {} - -#[cfg(target_os = "macos")] -fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { - use cocoa::appkit::{NSView, NSWindow, NSWindowButton}; - use cocoa::foundation::NSRect; - let ns_window = ns_window_handle.0 as cocoa::base::id; - unsafe { - let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let miniaturize = - ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let zoom = ns_window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - - let title_bar_container_view = close.superview().superview(); - - let close_rect: NSRect = msg_send![close, frame]; - let button_height = close_rect.size.height; - - let title_bar_frame_height = button_height + y; - let mut title_bar_rect = NSView::frame(title_bar_container_view); - title_bar_rect.size.height = title_bar_frame_height; - title_bar_rect.origin.y = NSView::frame(ns_window).size.height - title_bar_frame_height; - let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; - - let window_buttons = vec![close, miniaturize, zoom]; - let space_between = NSView::frame(miniaturize).origin.x - NSView::frame(close).origin.x; - - for (i, button) in window_buttons.into_iter().enumerate() { - let mut rect: NSRect = NSView::frame(button); - rect.origin.x = x + (i as f64 * space_between); - button.setFrameOrigin(rect.origin); - } - } -} - -#[cfg(target_os = "macos")] -#[derive(Debug)] -struct WindowState { - window: WebviewWindow, -} - -#[cfg(target_os = "macos")] -pub fn setup_traffic_light_positioner(window: WebviewWindow) { - use cocoa::appkit::NSWindow; - use cocoa::base::{id, BOOL}; - use cocoa::foundation::NSUInteger; - use objc::runtime::{Object, Sel}; - use std::ffi::c_void; - - // Do the initial positioning - position_traffic_lights( - UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), - WINDOW_CONTROL_PAD_X, - WINDOW_CONTROL_PAD_Y, - ); - - // Ensure they stay in place while resizing the window. - fn with_window_state) -> T, T>( - this: &Object, - func: F, - ) { - let ptr = unsafe { - let x: *mut c_void = *this.get_ivar("app_box"); - &mut *(x as *mut WindowState) - }; - func(ptr); - } - - unsafe { - let ns_win = window - .ns_window() - .expect("NS Window should exist to mount traffic light delegate.") - as id; - - let current_delegate: id = ns_win.delegate(); - - extern "C" fn on_window_should_close(this: &Object, _cmd: Sel, sender: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, windowShouldClose: sender] - } - } - extern "C" fn on_window_will_close(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillClose: notification]; - } - } - extern "C" fn on_window_did_resize(this: &Object, _cmd: Sel, notification: id) { - unsafe { - with_window_state(&*this, |state: &mut WindowState| { - let id = state - .window - .ns_window() - .expect("NS window should exist on state to handle resize") - as id; - - #[cfg(target_os = "macos")] - position_traffic_lights( - UnsafeWindowHandle(id as *mut std::ffi::c_void), - WINDOW_CONTROL_PAD_X, - WINDOW_CONTROL_PAD_Y, - ); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidResize: notification]; - } - } - extern "C" fn on_window_did_move(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidMove: notification]; - } - } - extern "C" fn on_window_did_change_backing_properties( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidChangeBackingProperties: notification]; - } - } - extern "C" fn on_window_did_become_key(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidBecomeKey: notification]; - } - } - extern "C" fn on_window_did_resign_key(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidResignKey: notification]; - } - } - extern "C" fn on_dragging_entered(this: &Object, _cmd: Sel, notification: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, draggingEntered: notification] - } - } - extern "C" fn on_prepare_for_drag_operation( - this: &Object, - _cmd: Sel, - notification: id, - ) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, prepareForDragOperation: notification] - } - } - extern "C" fn on_perform_drag_operation(this: &Object, _cmd: Sel, sender: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, performDragOperation: sender] - } - } - extern "C" fn on_conclude_drag_operation(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, concludeDragOperation: notification]; - } - } - extern "C" fn on_dragging_exited(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, draggingExited: notification]; - } - } - extern "C" fn on_window_will_use_full_screen_presentation_options( - this: &Object, - _cmd: Sel, - window: id, - proposed_options: NSUInteger, - ) -> NSUInteger { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, window: window willUseFullScreenPresentationOptions: proposed_options] - } - } - extern "C" fn on_window_did_enter_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(&*this, |state: &mut WindowState| { - state - .window - .emit("did-enter-fullscreen", ()) - .expect("Failed to emit event"); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidEnterFullScreen: notification]; - } - } - extern "C" fn on_window_will_enter_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(&*this, |state: &mut WindowState| { - state - .window - .emit("will-enter-fullscreen", ()) - .expect("Failed to emit event"); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillEnterFullScreen: notification]; - } - } - extern "C" fn on_window_did_exit_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(&*this, |state: &mut WindowState| { - state - .window - .emit("did-exit-fullscreen", ()) - .expect("Failed to emit event"); - - let id = state.window.ns_window().expect("Failed to emit event") as id; - position_traffic_lights( - UnsafeWindowHandle(id as *mut std::ffi::c_void), - WINDOW_CONTROL_PAD_X, - WINDOW_CONTROL_PAD_Y, - ); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidExitFullScreen: notification]; - } - } - extern "C" fn on_window_will_exit_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(&*this, |state: &mut WindowState| { - state - .window - .emit("will-exit-fullscreen", ()) - .expect("Failed to emit event"); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillExitFullScreen: notification]; - } - } - extern "C" fn on_window_did_fail_to_enter_full_screen( - this: &Object, - _cmd: Sel, - window: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidFailToEnterFullScreen: window]; - } - } - extern "C" fn on_effective_appearance_did_change( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, effectiveAppearanceDidChange: notification]; - } - } - extern "C" fn on_effective_appearance_did_changed_on_main_thread( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![ - super_del, - effectiveAppearanceDidChangedOnMainThread: notification - ]; - } - } - - // Are we deallocing this properly ? (I miss safe Rust :( ) - let window_label = window.label().to_string(); - - let app_state = WindowState { window }; - let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void; - let random_str: String = rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(20) - .map(char::from) - .collect(); - - // We need to ensure we have a unique delegate name, otherwise we will panic while trying to create a duplicate - // delegate with the same name. - let delegate_name = format!("windowDelegate_{}_{}", window_label, random_str); - - ns_win.setDelegate_(delegate!(&delegate_name, { - window: id = ns_win, - app_box: *mut c_void = app_box, - toolbar: id = cocoa::base::nil, - super_delegate: id = current_delegate, - (windowShouldClose:) => on_window_should_close as extern fn(&Object, Sel, id) -> BOOL, - (windowWillClose:) => on_window_will_close as extern fn(&Object, Sel, id), - (windowDidResize:) => on_window_did_resize:: as extern fn(&Object, Sel, id), - (windowDidMove:) => on_window_did_move as extern fn(&Object, Sel, id), - (windowDidChangeBackingProperties:) => on_window_did_change_backing_properties as extern fn(&Object, Sel, id), - (windowDidBecomeKey:) => on_window_did_become_key as extern fn(&Object, Sel, id), - (windowDidResignKey:) => on_window_did_resign_key as extern fn(&Object, Sel, id), - (draggingEntered:) => on_dragging_entered as extern fn(&Object, Sel, id) -> BOOL, - (prepareForDragOperation:) => on_prepare_for_drag_operation as extern fn(&Object, Sel, id) -> BOOL, - (performDragOperation:) => on_perform_drag_operation as extern fn(&Object, Sel, id) -> BOOL, - (concludeDragOperation:) => on_conclude_drag_operation as extern fn(&Object, Sel, id), - (draggingExited:) => on_dragging_exited as extern fn(&Object, Sel, id), - (window:willUseFullScreenPresentationOptions:) => on_window_will_use_full_screen_presentation_options as extern fn(&Object, Sel, id, NSUInteger) -> NSUInteger, - (windowDidEnterFullScreen:) => on_window_did_enter_full_screen:: as extern fn(&Object, Sel, id), - (windowWillEnterFullScreen:) => on_window_will_enter_full_screen:: as extern fn(&Object, Sel, id), - (windowDidExitFullScreen:) => on_window_did_exit_full_screen:: as extern fn(&Object, Sel, id), - (windowWillExitFullScreen:) => on_window_will_exit_full_screen:: as extern fn(&Object, Sel, id), - (windowDidFailToEnterFullScreen:) => on_window_did_fail_to_enter_full_screen as extern fn(&Object, Sel, id), - (effectiveAppearanceDidChange:) => on_effective_appearance_did_change as extern fn(&Object, Sel, id), - (effectiveAppearanceDidChangedOnMainThread:) => on_effective_appearance_did_changed_on_main_thread as extern fn(&Object, Sel, id) - })) - } -} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2e05b74..274a314 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -10,10 +10,21 @@ "frontendDist": "../dist/moonsound/browser" }, "app": { - "macOSPrivateApi": true, + "withGlobalTauri": true, "security": { "csp": null - } + }, + "windows": [ + { + "fullscreen": false, + "resizable": true, + "title": "tauri-app", + "width": 600, + "height": 400, + "titleBarStyle": "Overlay", + "hiddenTitle": true + } + ] }, "bundle": { "active": true, diff --git a/src/index.html b/src/index.html index f66cc07..8a5c482 100644 --- a/src/index.html +++ b/src/index.html @@ -10,6 +10,7 @@ html, body { background: transparent; + margin-top: 1rem; } -- 2.51.2