From 830084c426c8b8afd72415a649e623ada0105192 Mon Sep 17 00:00:00 2001 From: baiqing Date: Tue, 12 May 2026 15:23:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(ui):=20Windows=20=E4=B8=BB=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E4=BA=A4=E8=BF=98=E5=8E=9F=E7=94=9F=20chrome=EF=BC=8C?= =?UTF-8?q?PR=20#419=20=E5=88=A0=E8=87=AA=E5=AE=9A=E4=B9=89=E6=A0=87?= =?UTF-8?q?=E9=A2=98=E6=A0=8F=E7=9A=84=E5=B0=BE=E5=B7=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #419 删了 React 端 WinTitleBar 自定义标题栏,commit message 说"交还 Tauri decorations:true 原生 Win11 标题栏",但漏看 lib.rs 里有一段 Rust 代码在 setup 时**强制**调 set_decorations(false) 把原生 chrome 关掉 (原本是为了让自定义 WinTitleBar 接管)。 结果:v1.3.1-2-beta 上 Windows 主窗口完全无 chrome —— 无法拖动 / 无法 点 X 关闭 / 无法最小化,只能从 tray 退出。用户卡死。 修法: - lib.rs setup() Windows 分支:移除 set_decorations(false) + 移除 apply_windows_rounded_frame 调用,保留 apply_mica 给原生 chrome 提供 磨砂材质 - RunEvent Resized/ScaleFactorChanged 里也移除 apply_windows_rounded_frame 调用(原生 chrome 自带 resize border + 圆角) - apply_windows_rounded_frame 函数本身变成 dead code,整段删除(含 raw_window_handle / Win32 DwmSetWindowAttribute / SetWindowRgn 等 import) tauri.conf.json 的 decorations:true 配置不动,配合 hiddenTitle:true 让 原生标题栏接管。 --- openless-all/app/src-tauri/src/lib.rs | 112 ++------------------------ 1 file changed, 5 insertions(+), 107 deletions(-) diff --git a/openless-all/app/src-tauri/src/lib.rs b/openless-all/app/src-tauri/src/lib.rs index 7ace76be..25304735 100644 --- a/openless-all/app/src-tauri/src/lib.rs +++ b/openless-all/app/src-tauri/src/lib.rs @@ -145,15 +145,14 @@ pub fn run() { #[cfg(target_os = "windows")] { use window_vibrancy::apply_mica; - // The window starts hidden so Windows native chrome can be disabled before - // the first show; doing this after the native frame is visible is unreliable. - if let Err(e) = main.set_decorations(false) { - log::warn!("[main] disable native decorations failed: {e}"); - } + // Windows 走 Tauri decorations:true 原生 Win11 标题栏 / 关闭按钮 / + // 拖动 / 圆角 / resize border。PR #419 删除自定义 WinTitleBar 后, + // 早先的 set_decorations(false) + apply_windows_rounded_frame 链路 + // 会让窗口完全无 chrome,用户无法拖/关/最小化(只能 tray 退出)。 + // 保留 apply_mica 给原生 chrome 提供磨砂材质。 if let Err(e) = apply_mica(&main, None) { log::warn!("[main] mica failed: {e}"); } - apply_windows_rounded_frame(&main); } // 静默启动开关:prefs.start_minimized = true → 不弹主窗口, // 用户从菜单栏 / 托盘点击访问。开机自启时尤其有用,避免每次 @@ -339,16 +338,6 @@ pub fn run() { api.prevent_close(); hide_main_window(app); } - #[cfg(target_os = "windows")] - if matches!( - event, - tauri::WindowEvent::Resized(_) - | tauri::WindowEvent::ScaleFactorChanged { .. } - ) { - if let Some(main) = app.get_webview_window("main") { - apply_windows_rounded_frame(&main); - } - } } } RunEvent::Exit => { @@ -615,97 +604,6 @@ fn handle_style_tray_menu_event(app: &AppHandle, id: &str) -> bool { true } -#[cfg(target_os = "windows")] -fn apply_windows_rounded_frame(window: &tauri::WebviewWindow) { - use raw_window_handle::{HasWindowHandle, RawWindowHandle}; - use windows::Win32::Foundation::{BOOL, HWND, RECT}; - use windows::Win32::Graphics::Dwm::{ - DwmSetWindowAttribute, DWMWA_BORDER_COLOR, DWMWA_WINDOW_CORNER_PREFERENCE, DWMWCP_ROUND, - }; - use windows::Win32::Graphics::Gdi::{CreateRoundRectRgn, SetWindowRgn, HRGN}; - use windows::Win32::UI::WindowsAndMessaging::{ - GetWindowLongW, GetWindowRect, SetWindowLongW, SetWindowPos, GWL_STYLE, SWP_FRAMECHANGED, - SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, WS_CAPTION, WS_THICKFRAME, - }; - - let handle = match window.window_handle().map(|h| h.as_raw()) { - Ok(RawWindowHandle::Win32(handle)) => handle, - Ok(other) => { - log::warn!("[main] unexpected raw window handle for DWM frame: {other:?}"); - return; - } - Err(e) => { - log::warn!("[main] read raw window handle failed: {e}"); - return; - } - }; - let hwnd = HWND(handle.hwnd.get() as *mut core::ffi::c_void); - - unsafe { - let style = GetWindowLongW(hwnd, GWL_STYLE); - let desired_style = (style | WS_THICKFRAME.0 as i32) & !(WS_CAPTION.0 as i32); - if style != desired_style { - SetWindowLongW(hwnd, GWL_STYLE, desired_style); - if let Err(e) = SetWindowPos( - hwnd, - HWND::default(), - 0, - 0, - 0, - 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED, - ) { - log::warn!("[main] refresh native frame after style update failed: {e}"); - } - } - - if window.is_maximized().unwrap_or(false) { - let _ = SetWindowRgn(hwnd, HRGN::default(), BOOL(1)); - return; - } - - let corner_preference = DWMWCP_ROUND; - if let Err(e) = DwmSetWindowAttribute( - hwnd, - DWMWA_WINDOW_CORNER_PREFERENCE, - &corner_preference as *const _ as *const core::ffi::c_void, - std::mem::size_of_val(&corner_preference) as u32, - ) { - log::warn!("[main] set DWM rounded corners failed: {e}"); - } - - // Remove DWM's fallback 1px light border; the React shell draws the visual stroke. - let border_color_none: u32 = 0xFFFFFFFE; - if let Err(e) = DwmSetWindowAttribute( - hwnd, - DWMWA_BORDER_COLOR, - &border_color_none as *const _ as *const core::ffi::c_void, - std::mem::size_of_val(&border_color_none) as u32, - ) { - log::warn!("[main] remove DWM border color failed: {e}"); - } - - let mut rect = RECT::default(); - if let Err(e) = GetWindowRect(hwnd, &mut rect) { - log::warn!("[main] read window rect for rounded region failed: {e}"); - return; - } - let width = rect.right - rect.left; - let height = rect.bottom - rect.top; - if width <= 0 || height <= 0 { - return; - } - let region = CreateRoundRectRgn(0, 0, width + 1, height + 1, 18, 18); - if region.is_invalid() { - log::warn!("[main] create rounded window region failed"); - return; - } - if SetWindowRgn(hwnd, region, BOOL(1)) == 0 { - log::warn!("[main] apply rounded window region failed"); - } - } -} - #[tauri::command] fn restart_app(app: AppHandle) { // macOS:自动更新会让新装的 .app 带 com.apple.quarantine(无论 Tauri updater