feat: unify window manager and optimize window show/hide logic

This commit is contained in:
wonfen
2025-06-17 13:02:47 +08:00
Unverified
parent a67e8388a9
commit fc30fab9cd
6 changed files with 305 additions and 43 deletions

View File

@@ -272,10 +272,11 @@ impl Hotkey {
if is_enable_global_hotkey {
f();
} else if let Some(window) = app_handle.get_webview_window("main") {
} else {
use crate::utils::window_manager::WindowManager;
// 非轻量模式且未启用全局热键时,只在窗口可见且有焦点的情况下响应热键
let is_visible = window.is_visible().unwrap_or(false);
let is_focused = window.is_focused().unwrap_or(false);
let is_visible = WindowManager::is_main_window_visible();
let is_focused = WindowManager::is_main_window_focused();
if is_focused && is_visible {
f();

View File

@@ -10,7 +10,6 @@ use crate::{
lightweight::{entry_lightweight_mode, is_in_lightweight_mode},
mihomo::Rate,
},
resolve,
utils::{dirs::find_target_icons, i18n::t, resolve::VERSION},
Type,
};
@@ -653,13 +652,14 @@ impl Tray {
"system_proxy" => feat::toggle_system_proxy(),
"tun_mode" => feat::toggle_tun_mode(None),
"main_window" => {
use crate::utils::window_manager::WindowManager;
log::info!(target: "app", "Tray点击事件: 显示主窗口");
if crate::module::lightweight::is_in_lightweight_mode() {
log::info!(target: "app", "当前在轻量模式,正在退出轻量模式");
crate::module::lightweight::exit_lightweight_mode();
}
let result = resolve::create_window(true);
log::info!(target: "app", "窗口创建/显示结果: {}", result);
let result = WindowManager::show_main_window();
log::info!(target: "app", "窗口显示结果: {:?}", result);
}
_ => {}
}
@@ -920,12 +920,16 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) {
feat::change_clash_mode(mode.into());
}
"open_window" => {
use crate::utils::window_manager::WindowManager;
log::info!(target: "app", "托盘菜单点击: 打开窗口");
// 如果在轻量模式中,先退出轻量模式
if crate::module::lightweight::is_in_lightweight_mode() {
log::info!(target: "app", "当前在轻量模式,正在退出");
crate::module::lightweight::exit_lightweight_mode();
}
// 然后创建窗口
let _ = resolve::create_window(true);
// 使用统一的窗口管理器显示窗口
let result = WindowManager::show_main_window();
log::info!(target: "app", "窗口显示结果: {:?}", result);
}
"system_proxy" => feat::toggle_system_proxy(),
"tun_mode" => feat::toggle_tun_mode(None),

View File

@@ -5,53 +5,29 @@ use crate::{
core::{handle, sysopt, CoreManager},
logging,
module::mihomo::MihomoManager,
utils::{logging::Type, resolve},
utils::logging::Type,
};
/// Open or close the dashboard window
#[allow(dead_code)]
pub fn open_or_close_dashboard() {
use crate::utils::window_manager::WindowManager;
log::info!(target: "app", "Attempting to open/close dashboard");
// 检查是否在轻量模式下
if crate::module::lightweight::is_in_lightweight_mode() {
log::info!(target: "app", "Currently in lightweight mode, exiting lightweight mode");
crate::module::lightweight::exit_lightweight_mode();
log::info!(target: "app", "Creating new window after exiting lightweight mode");
resolve::create_window(true);
let result = WindowManager::show_main_window();
log::info!(target: "app", "Window operation result: {:?}", result);
return;
}
if let Some(window) = handle::Handle::global().get_window() {
log::info!(target: "app", "Found existing window");
// 如果窗口存在,则切换其显示状态
match window.is_visible() {
Ok(visible) => {
log::info!(target: "app", "Window visibility status: {}", visible);
if visible {
log::info!(target: "app", "Attempting to hide window");
let _ = window.hide();
} else {
log::info!(target: "app", "Attempting to show and focus window");
if window.is_minimized().unwrap_or(false) {
let _ = window.unminimize();
}
let _ = window.show();
let _ = window.set_focus();
}
}
Err(e) => {
log::error!(target: "app", "Failed to get window visibility: {:?}", e);
}
}
} else {
log::info!(target: "app", "No existing window found, creating new window");
resolve::create_window(true);
}
// 使用统一的窗口管理器切换窗口状态
let result = WindowManager::toggle_main_window();
log::info!(target: "app", "Window toggle result: {:?}", result);
}
/// 异步优化的应用退出函数

View File

@@ -93,10 +93,18 @@ pub fn disable_auto_light_weight_mode() {
}
pub fn entry_lightweight_mode() {
use crate::utils::window_manager::WindowManager;
let result = WindowManager::hide_main_window();
logging!(
info,
Type::Lightweight,
true,
"轻量模式隐藏窗口结果: {:?}",
result
);
if let Some(window) = handle::Handle::global().get_window() {
if window.is_visible().unwrap_or(false) {
let _ = window.hide();
}
if let Some(webview) = window.get_webview_window("main") {
let _ = webview.destroy();
}

View File

@@ -8,3 +8,4 @@ pub mod network;
pub mod resolve;
pub mod server;
pub mod tmpl;
pub mod window_manager;

View File

@@ -0,0 +1,272 @@
use crate::{core::handle, logging, utils::logging::Type};
use tauri::{Manager, WebviewWindow, Wry};
#[cfg(target_os = "macos")]
use crate::AppHandleManager;
/// 窗口操作结果
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum WindowOperationResult {
/// 窗口已显示并获得焦点
Shown,
/// 窗口已隐藏
Hidden,
/// 创建了新窗口
Created,
/// 操作失败
Failed,
/// 无需操作
NoAction,
}
/// 窗口状态
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum WindowState {
/// 窗口可见且有焦点
VisibleFocused,
/// 窗口可见但无焦点
VisibleUnfocused,
/// 窗口最小化
Minimized,
/// 窗口隐藏
Hidden,
/// 窗口不存在
NotExist,
}
/// 统一的窗口管理器
pub struct WindowManager;
impl WindowManager {
pub fn get_main_window_state() -> WindowState {
if let Some(window) = Self::get_main_window() {
if window.is_minimized().unwrap_or(false) {
WindowState::Minimized
} else if window.is_visible().unwrap_or(false) {
if window.is_focused().unwrap_or(false) {
WindowState::VisibleFocused
} else {
WindowState::VisibleUnfocused
}
} else {
WindowState::Hidden
}
} else {
WindowState::NotExist
}
}
/// 获取主窗口实例
pub fn get_main_window() -> Option<WebviewWindow<Wry>> {
handle::Handle::global()
.app_handle()
.and_then(|app| app.get_webview_window("main"))
}
/// 智能显示主窗口
pub fn show_main_window() -> WindowOperationResult {
logging!(info, Type::Window, true, "开始智能显示主窗口");
logging!(
debug,
Type::Window,
true,
"{}",
Self::get_window_status_info()
);
let current_state = Self::get_main_window_state();
match current_state {
WindowState::NotExist => {
logging!(info, Type::Window, true, "窗口不存在,创建新窗口");
if Self::create_new_window() {
WindowOperationResult::Created
} else {
WindowOperationResult::Failed
}
}
WindowState::VisibleFocused => {
logging!(info, Type::Window, true, "窗口已经可见且有焦点,无需操作");
WindowOperationResult::NoAction
}
WindowState::VisibleUnfocused | WindowState::Minimized | WindowState::Hidden => {
if let Some(window) = Self::get_main_window() {
Self::activate_window(&window)
} else {
WindowOperationResult::Failed
}
}
}
}
/// 切换主窗口显示状态(显示/隐藏)
pub fn toggle_main_window() -> WindowOperationResult {
logging!(info, Type::Window, true, "开始切换主窗口显示状态");
let current_state = Self::get_main_window_state();
logging!(
info,
Type::Window,
true,
"当前窗口状态: {:?}",
current_state
);
match current_state {
WindowState::NotExist => {
// 窗口不存在,创建新窗口
if Self::create_new_window() {
WindowOperationResult::Created
} else {
WindowOperationResult::Failed
}
}
WindowState::VisibleFocused => {
// 窗口可见且有焦点,隐藏它
if let Some(window) = Self::get_main_window() {
if window.hide().is_ok() {
logging!(info, Type::Window, true, "窗口已隐藏");
WindowOperationResult::Hidden
} else {
WindowOperationResult::Failed
}
} else {
WindowOperationResult::Failed
}
}
WindowState::VisibleUnfocused | WindowState::Minimized | WindowState::Hidden => {
// 窗口存在但不可见或无焦点,激活它
if let Some(window) = Self::get_main_window() {
Self::activate_window(&window)
} else {
WindowOperationResult::Failed
}
}
}
}
/// 激活窗口(取消最小化、显示、设置焦点)
fn activate_window(window: &WebviewWindow<Wry>) -> WindowOperationResult {
logging!(info, Type::Window, true, "开始激活窗口");
let mut operations_successful = true;
// 1. 如果窗口最小化,先取消最小化
if window.is_minimized().unwrap_or(false) {
logging!(info, Type::Window, true, "窗口已最小化,正在取消最小化");
if let Err(e) = window.unminimize() {
logging!(warn, Type::Window, true, "取消最小化失败: {}", e);
operations_successful = false;
}
}
// 2. 显示窗口
if let Err(e) = window.show() {
logging!(warn, Type::Window, true, "显示窗口失败: {}", e);
operations_successful = false;
}
// 3. 设置焦点
if let Err(e) = window.set_focus() {
logging!(warn, Type::Window, true, "设置窗口焦点失败: {}", e);
operations_successful = false;
}
// 4. 平台特定的激活策略
#[cfg(target_os = "macos")]
{
logging!(info, Type::Window, true, "应用 macOS 特定的激活策略");
AppHandleManager::global().set_activation_policy_regular();
}
#[cfg(target_os = "windows")]
{
// Windows 尝试额外的激活方法
if let Err(e) = window.set_always_on_top(true) {
logging!(
debug,
Type::Window,
true,
"设置置顶失败(非关键错误): {}",
e
);
}
// 立即取消置顶
if let Err(e) = window.set_always_on_top(false) {
logging!(
debug,
Type::Window,
true,
"取消置顶失败(非关键错误): {}",
e
);
}
}
if operations_successful {
logging!(info, Type::Window, true, "窗口激活成功");
WindowOperationResult::Shown
} else {
logging!(warn, Type::Window, true, "窗口激活部分失败");
WindowOperationResult::Failed
}
}
/// 隐藏主窗口
pub fn hide_main_window() -> WindowOperationResult {
logging!(info, Type::Window, true, "开始隐藏主窗口");
if let Some(window) = Self::get_main_window() {
if window.hide().is_ok() {
logging!(info, Type::Window, true, "窗口已隐藏");
WindowOperationResult::Hidden
} else {
logging!(warn, Type::Window, true, "隐藏窗口失败");
WindowOperationResult::Failed
}
} else {
logging!(info, Type::Window, true, "窗口不存在,无需隐藏");
WindowOperationResult::NoAction
}
}
/// 检查窗口是否可见
pub fn is_main_window_visible() -> bool {
Self::get_main_window()
.map(|window| window.is_visible().unwrap_or(false))
.unwrap_or(false)
}
/// 检查窗口是否有焦点
pub fn is_main_window_focused() -> bool {
Self::get_main_window()
.map(|window| window.is_focused().unwrap_or(false))
.unwrap_or(false)
}
/// 检查窗口是否最小化
pub fn is_main_window_minimized() -> bool {
Self::get_main_window()
.map(|window| window.is_minimized().unwrap_or(false))
.unwrap_or(false)
}
/// 创建新窗口现有的实现
fn create_new_window() -> bool {
use crate::utils::resolve;
resolve::create_window(true)
}
/// 获取详细的窗口状态信息
pub fn get_window_status_info() -> String {
let state = Self::get_main_window_state();
let is_visible = Self::is_main_window_visible();
let is_focused = Self::is_main_window_focused();
let is_minimized = Self::is_main_window_minimized();
format!(
"窗口状态: {:?} | 可见: {} | 有焦点: {} | 最小化: {}",
state, is_visible, is_focused, is_minimized
)
}
}