fix(tauri): prevent Windows zoom freeze with debouncing and transparent window
- Add 50ms debounce to zoom operations to prevent WebView2 IPC bottleneck - Enable transparent window mode for better Windows resize/zoom performance - Reduce zoom step from 0.2 to 0.1 for finer control
This commit is contained in:
@@ -9,11 +9,13 @@ use serde_json::json;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{Instant, SystemTime, UNIX_EPOCH};
|
||||||
use tauri::menu::{MenuBuilder, MenuItem, SubmenuBuilder};
|
use tauri::menu::{MenuBuilder, MenuItem, SubmenuBuilder};
|
||||||
use tauri::plugin::{Builder as PluginBuilder, TauriPlugin};
|
use tauri::plugin::{Builder as PluginBuilder, TauriPlugin};
|
||||||
use tauri::webview::Webview;
|
use tauri::webview::Webview;
|
||||||
use tauri::{AppHandle, Emitter, Manager, Runtime, WebviewUrl, WebviewWindowBuilder, WindowEvent, Wry};
|
use tauri::{
|
||||||
|
AppHandle, Emitter, Manager, Runtime, WebviewUrl, WebviewWindowBuilder, WindowEvent, Wry,
|
||||||
|
};
|
||||||
use tauri_plugin_global_shortcut::{
|
use tauri_plugin_global_shortcut::{
|
||||||
Code as ShortcutCode, GlobalShortcutExt, Shortcut, ShortcutState,
|
Code as ShortcutCode, GlobalShortcutExt, Shortcut, ShortcutState,
|
||||||
};
|
};
|
||||||
@@ -30,10 +32,12 @@ use std::os::windows::ffi::OsStrExt;
|
|||||||
use windows_sys::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID;
|
use windows_sys::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID;
|
||||||
|
|
||||||
static QUIT_REQUESTED: AtomicBool = AtomicBool::new(false);
|
static QUIT_REQUESTED: AtomicBool = AtomicBool::new(false);
|
||||||
|
static LAST_ZOOM_TIME: Mutex<Option<Instant>> = Mutex::new(None);
|
||||||
const DEFAULT_ZOOM_LEVEL: f64 = 1.0;
|
const DEFAULT_ZOOM_LEVEL: f64 = 1.0;
|
||||||
const ZOOM_STEP: f64 = 0.2;
|
const ZOOM_STEP: f64 = 0.1;
|
||||||
const MIN_ZOOM_LEVEL: f64 = 0.2;
|
const MIN_ZOOM_LEVEL: f64 = 0.2;
|
||||||
const MAX_ZOOM_LEVEL: f64 = 5.0;
|
const MAX_ZOOM_LEVEL: f64 = 5.0;
|
||||||
|
const ZOOM_DEBOUNCE_MS: u64 = 50;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
const WINDOWS_APP_USER_MODEL_ID: &str = "ai.neuralnomads.codenomad.client";
|
const WINDOWS_APP_USER_MODEL_ID: &str = "ai.neuralnomads.codenomad.client";
|
||||||
@@ -129,7 +133,11 @@ fn should_allow_internal(url: &Url) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_allow_window_origin<R: Runtime>(app_handle: &AppHandle<R>, window_label: &str, url: &Url) -> bool {
|
fn should_allow_window_origin<R: Runtime>(
|
||||||
|
app_handle: &AppHandle<R>,
|
||||||
|
window_label: &str,
|
||||||
|
url: &Url,
|
||||||
|
) -> bool {
|
||||||
if should_allow_internal(url) {
|
if should_allow_internal(url) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -172,7 +180,11 @@ fn open_remote_window(app: AppHandle, payload: RemoteWindowPayload) -> Result<()
|
|||||||
|
|
||||||
let parsed = Url::parse(&payload.base_url).map_err(|err| err.to_string())?;
|
let parsed = Url::parse(&payload.base_url).map_err(|err| err.to_string())?;
|
||||||
let label = format!("remote-{}", payload.id);
|
let label = format!("remote-{}", payload.id);
|
||||||
let title = format!("{} - {}", payload.name, parsed.host_str().unwrap_or(payload.base_url.as_str()));
|
let title = format!(
|
||||||
|
"{} - {}",
|
||||||
|
payload.name,
|
||||||
|
parsed.host_str().unwrap_or(payload.base_url.as_str())
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(existing) = app.get_webview_window(&label) {
|
if let Some(existing) = app.get_webview_window(&label) {
|
||||||
let _ = existing.navigate(parsed.clone());
|
let _ = existing.navigate(parsed.clone());
|
||||||
@@ -189,12 +201,13 @@ fn open_remote_window(app: AppHandle, payload: RemoteWindowPayload) -> Result<()
|
|||||||
.map_err(|err| err.to_string())?
|
.map_err(|err| err.to_string())?
|
||||||
.insert(label.clone(), parsed.origin().ascii_serialization());
|
.insert(label.clone(), parsed.origin().ascii_serialization());
|
||||||
|
|
||||||
let window = WebviewWindowBuilder::new(&app, label.clone(), WebviewUrl::External(parsed.clone()))
|
let window =
|
||||||
.title(title)
|
WebviewWindowBuilder::new(&app, label.clone(), WebviewUrl::External(parsed.clone()))
|
||||||
.inner_size(1400.0, 900.0)
|
.title(title)
|
||||||
.min_inner_size(800.0, 600.0)
|
.inner_size(1400.0, 900.0)
|
||||||
.build()
|
.min_inner_size(800.0, 600.0)
|
||||||
.map_err(|err| err.to_string())?;
|
.build()
|
||||||
|
.map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
let app_handle = app.clone();
|
let app_handle = app.clone();
|
||||||
window.on_window_event(move |event| {
|
window.on_window_event(move |event| {
|
||||||
@@ -246,6 +259,15 @@ fn clamp_zoom_level(value: f64) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_main_window_zoom(app_handle: &AppHandle, next_zoom: f64) {
|
fn set_main_window_zoom(app_handle: &AppHandle, next_zoom: f64) {
|
||||||
|
if let Ok(mut last_zoom_time) = LAST_ZOOM_TIME.lock() {
|
||||||
|
if let Some(last_time) = *last_zoom_time {
|
||||||
|
if last_time.elapsed().as_millis() < ZOOM_DEBOUNCE_MS as u128 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*last_zoom_time = Some(Instant::now());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(window) = app_handle.get_webview_window("main") {
|
if let Some(window) = app_handle.get_webview_window("main") {
|
||||||
let normalized = clamp_zoom_level(next_zoom);
|
let normalized = clamp_zoom_level(next_zoom);
|
||||||
if window.set_zoom(normalized).is_ok() {
|
if window.set_zoom(normalized).is_ok() {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"resizable": true,
|
"resizable": true,
|
||||||
"fullscreen": false,
|
"fullscreen": false,
|
||||||
"decorations": true,
|
"decorations": true,
|
||||||
|
"transparent": true,
|
||||||
"theme": "Dark",
|
"theme": "Dark",
|
||||||
"backgroundColor": "#1a1a1a",
|
"backgroundColor": "#1a1a1a",
|
||||||
"zoomHotkeysEnabled": true
|
"zoomHotkeysEnabled": true
|
||||||
|
|||||||
Reference in New Issue
Block a user