use serde::Deserialize;
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime, Webview,
};
#[cfg(target_os = "macos")]
mod macos;
fn default_enabled() -> bool {
true
}
#[derive(Debug, Deserialize)]
pub struct Config {
#[serde(default = "default_enabled")]
pub enabled: bool,
}
impl Default for Config {
fn default() -> Self {
Self { enabled: true }
}
}
struct PluginState {
enabled: bool,
}
pub trait MacFpsExt<R: Runtime> {
fn unlock_fps(&self) -> tauri::Result<()>;
fn lock_fps(&self) -> tauri::Result<()>;
}
impl<R: Runtime> MacFpsExt<R> for Webview<R> {
fn unlock_fps(&self) -> tauri::Result<()> {
#[cfg(target_os = "macos")]
{
self.with_webview(|webview| {
let ptr = webview.inner();
if let Err(e) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe {
macos::disable_60fps_cap(ptr);
})) {
log::error!("tauri-plugin-macos-fps: panic in unlock_fps: {:?}", e);
}
})?;
}
Ok(())
}
fn lock_fps(&self) -> tauri::Result<()> {
#[cfg(target_os = "macos")]
{
self.with_webview(|webview| {
let ptr = webview.inner();
if let Err(e) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe {
macos::enable_60fps_cap(ptr);
})) {
log::error!("tauri-plugin-macos-fps: panic in lock_fps: {:?}", e);
}
})?;
}
Ok(())
}
}
pub fn init<R: Runtime>() -> TauriPlugin<R, Config> {
Builder::<R, Config>::new("macos-fps")
.setup(|app, api| {
let enabled = api.config().enabled;
if !enabled {
log::info!("tauri-plugin-macos-fps: disabled via configuration");
}
app.manage(PluginState { enabled });
Ok(())
})
.on_webview_ready(|webview| {
let enabled = webview
.try_state::<PluginState>()
.map(|s| s.enabled)
.unwrap_or(true);
if !enabled {
return;
}
#[cfg(target_os = "macos")]
{
let _ = webview.with_webview(|wv| {
let ptr = wv.inner();
if let Err(e) =
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe {
macos::disable_60fps_cap(ptr);
}))
{
log::error!(
"tauri-plugin-macos-fps: panic in on_webview_ready: {:?}",
e
);
}
});
}
#[cfg(not(target_os = "macos"))]
{
let _ = webview;
}
})
.build()
}