diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 67da2ed..39707c8 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -136,6 +136,9 @@ pub fn run() { if let Err(error) = macos::allow_media_autoplay(&window) { log::warn!(target: "launcher", "{error}"); } + if let Err(error) = macos::activate_and_focus_window(&window) { + log::warn!(target: "launcher", "Could not focus launcher window on startup: {error}"); + } } Ok(()) @@ -235,6 +238,9 @@ pub fn run() { if let Err(error) = macos::allow_media_autoplay(&window) { log::warn!(target: "launcher", "{error}"); } + if let Err(error) = macos::activate_and_focus_window(&window) { + log::warn!(target: "launcher", "Could not focus launcher window on ready: {error}"); + } } presence::handle_run_event(app, &event); diff --git a/src-tauri/src/macos.rs b/src-tauri/src/macos.rs index a6d5294..a657b85 100644 --- a/src-tauri/src/macos.rs +++ b/src-tauri/src/macos.rs @@ -96,6 +96,14 @@ pub fn allow_media_autoplay(window: &tauri::WebviewWindow) -> Result<(), String> use objc2::msg_send; use objc2::runtime::AnyObject; + unsafe extern "C" { + fn object_getInstanceVariable( + obj: *mut AnyObject, + name: *const std::ffi::c_char, + out_value: *mut *mut std::ffi::c_void, + ) -> *const std::ffi::c_void; + } + window .with_webview(|webview| unsafe { let webview = webview.inner() as *mut AnyObject; @@ -103,7 +111,18 @@ pub fn allow_media_autoplay(window: &tauri::WebviewWindow) -> Result<(), String> return; } - let configuration: *mut AnyObject = msg_send![webview, configuration]; + // -[WKWebView configuration] returns a copy. To affect live playback, + // access the internal `_configuration` ivar directly when available. + let mut raw_config: *mut std::ffi::c_void = std::ptr::null_mut(); + let ivar_name = c"_configuration"; + let ivar = object_getInstanceVariable(webview, ivar_name.as_ptr(), &mut raw_config); + let configuration: *mut AnyObject = if !ivar.is_null() && !raw_config.is_null() { + log::debug!(target: "launcher", "Accessing live WKWebView._configuration ivar"); + raw_config as *mut AnyObject + } else { + msg_send![webview, configuration] + }; + if configuration.is_null() { return; } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3832826..917701a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -21,7 +21,8 @@ "decorations": false, "resizable": false, "maximizable": false, - "shadow": true + "shadow": true, + "focus": true } ], "withGlobalTauri": true, diff --git a/src/app.css b/src/app.css index 951bf04..23dfe7c 100644 --- a/src/app.css +++ b/src/app.css @@ -172,17 +172,21 @@ [role="button"]:not([disabled]) { cursor: pointer; } - - /* Suppress browser and WebKit native media controls and overlay play buttons on theme videos */ - video::-webkit-media-controls, - video::-webkit-media-controls-enclosure, - video::-webkit-media-controls-panel, - video::-webkit-media-controls-play-button, - video::-webkit-media-controls-start-playback-button, - video::-webkit-media-controls-overlay-play-button { - display: none !important; - -webkit-appearance: none !important; - opacity: 0 !important; - pointer-events: none !important; - } +} + +/* Suppress browser and WebKit native media controls and overlay play buttons on theme videos */ +video::-webkit-media-controls, +video::-webkit-media-controls-enclosure, +video::-webkit-media-controls-panel, +video::-webkit-media-controls-play-button, +video::-webkit-media-controls-start-playback-button, +video::-webkit-media-controls-overlay-play-button, +video::-webkit-media-controls-overlay-enclosure { + display: none !important; + -webkit-appearance: none !important; + opacity: 0 !important; + visibility: hidden !important; + pointer-events: none !important; + width: 0 !important; + height: 0 !important; } diff --git a/src/lib/components/ui/titlebar/titlebar.svelte b/src/lib/components/ui/titlebar/titlebar.svelte index 831d210..41a7ccd 100644 --- a/src/lib/components/ui/titlebar/titlebar.svelte +++ b/src/lib/components/ui/titlebar/titlebar.svelte @@ -27,57 +27,55 @@