feat: 新增「猫咪设置 > 窗口设置 > 窗口置顶」配置项 (#384)

This commit is contained in:
ayangweb
2025-05-27 00:57:57 +08:00
committed by GitHub
parent 0da9605e95
commit 424d052077
11 changed files with 76 additions and 16 deletions

View File

@@ -1,7 +1,8 @@
use tauri::{AppHandle, Emitter, EventTarget, WebviewWindow};
use tauri_nspanel::{
WebviewWindowExt,
cocoa::appkit::{NSMainMenuWindowLevel, NSWindowCollectionBehavior},
panel_delegate, WebviewWindowExt,
panel_delegate,
};
use tauri_plugin_custom_window::MAIN_WINDOW_LABEL;

View File

@@ -1,4 +1,4 @@
const COMMANDS: &[&str] = &["show_window", "hide_window"];
const COMMANDS: &[&str] = &["show_window", "hide_window", "set_always_on_top"];
fn main() {
tauri_plugin::Builder::new(COMMANDS).build();

View File

@@ -2,4 +2,4 @@
[default]
description = "Default permissions for the plugin"
permissions = ["allow-show-window", "allow-hide-window"]
permissions = ["allow-show-window", "allow-hide-window", "allow-set-always-on-top"]

View File

@@ -1,11 +1,12 @@
use super::{is_main_window, shared_hide_window, shared_show_window};
use super::{is_main_window, shared_hide_window, shared_set_always_on_top, shared_show_window};
use crate::MAIN_WINDOW_LABEL;
use tauri::{command, AppHandle, Runtime, WebviewWindow};
use tauri_nspanel::ManagerExt;
use tauri::{AppHandle, Runtime, WebviewWindow, command};
use tauri_nspanel::{ManagerExt, cocoa::appkit::NSMainMenuWindowLevel};
pub enum MacOSPanelStatus {
Show,
Hide,
SetAlwaysOnTop(bool),
}
#[command]
@@ -26,6 +27,23 @@ pub async fn hide_window<R: Runtime>(app_handle: AppHandle<R>, window: WebviewWi
}
}
#[command]
pub async fn set_always_on_top<R: Runtime>(
app_handle: AppHandle<R>,
window: WebviewWindow<R>,
always_on_top: bool,
) {
if is_main_window(&window) {
set_macos_panel(
&app_handle,
&window,
MacOSPanelStatus::SetAlwaysOnTop(always_on_top),
);
} else {
shared_set_always_on_top(&app_handle, &window, always_on_top);
}
}
pub fn set_macos_panel<R: Runtime>(
app_handle: &AppHandle<R>,
window: &WebviewWindow<R>,
@@ -43,6 +61,13 @@ pub fn set_macos_panel<R: Runtime>(
MacOSPanelStatus::Hide => {
panel.order_out(None);
}
MacOSPanelStatus::SetAlwaysOnTop(always_on_top) => {
if always_on_top {
panel.set_level(NSMainMenuWindowLevel);
} else {
panel.set_level(-1);
};
}
}
}
});

View File

@@ -1,4 +1,4 @@
use tauri::{async_runtime::spawn, AppHandle, Manager, Runtime, WebviewWindow};
use tauri::{AppHandle, Manager, Runtime, WebviewWindow, async_runtime::spawn};
pub static MAIN_WINDOW_LABEL: &str = "main";
pub static PREFERENCE_WINDOW_LABEL: &str = "preference";
@@ -19,18 +19,26 @@ pub fn is_main_window<R: Runtime>(window: &WebviewWindow<R>) -> bool {
window.label() == MAIN_WINDOW_LABEL
}
fn shared_show_window<R: Runtime>(app_handle: &AppHandle<R>, window: &WebviewWindow<R>) {
fn shared_show_window<R: Runtime>(_app_handle: &AppHandle<R>, window: &WebviewWindow<R>) {
let _ = window.show();
let _ = window.unminimize();
let _ = window.set_focus();
let _ = app_handle;
}
fn shared_hide_window<R: Runtime>(app_handle: &AppHandle<R>, window: &WebviewWindow<R>) {
fn shared_hide_window<R: Runtime>(_app_handle: &AppHandle<R>, window: &WebviewWindow<R>) {
let _ = window.hide();
}
let _ = app_handle;
fn shared_set_always_on_top<R: Runtime>(
_app_handle: &AppHandle<R>,
window: &WebviewWindow<R>,
always_on_top: bool,
) {
if always_on_top {
let _ = window.set_always_on_top(true);
} else {
let _ = window.set_always_on_bottom(true);
}
}
pub fn show_main_window(app_handle: &AppHandle) {

View File

@@ -1,5 +1,5 @@
use super::{shared_hide_window, shared_show_window};
use tauri::{command, AppHandle, Runtime, WebviewWindow};
use super::{shared_hide_window, shared_set_always_on_top, shared_show_window};
use tauri::{AppHandle, Runtime, WebviewWindow, command};
#[command]
pub async fn show_window<R: Runtime>(app_handle: AppHandle<R>, window: WebviewWindow<R>) {
@@ -10,3 +10,12 @@ pub async fn show_window<R: Runtime>(app_handle: AppHandle<R>, window: WebviewWi
pub async fn hide_window<R: Runtime>(app_handle: AppHandle<R>, window: WebviewWindow<R>) {
shared_hide_window(&app_handle, &window);
}
#[command]
pub async fn set_always_on_top<R: Runtime>(
app_handle: AppHandle<R>,
window: WebviewWindow<R>,
always_on_top: bool,
) {
shared_set_always_on_top(&app_handle, &window, always_on_top);
}

View File

@@ -1,7 +1,6 @@
use tauri::{
generate_handler,
Runtime, generate_handler,
plugin::{Builder, TauriPlugin},
Runtime,
};
mod commands;
@@ -13,6 +12,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
.invoke_handler(generate_handler![
commands::show_window,
commands::hide_window,
commands::set_always_on_top
])
.build()
}

View File

@@ -8,6 +8,7 @@ import { onUnmounted, ref, watch } from 'vue'
import { useDevice } from '@/composables/useDevice'
import { useModel } from '@/composables/useModel'
import { useSharedMenu } from '@/composables/useSharedMenu'
import { setAlwaysOnTop } from '@/plugins/window'
import { useCatStore } from '@/stores/cat'
import { useModelStore } from '@/stores/model'
import { join } from '@/utils/path'
@@ -51,6 +52,8 @@ watch(() => catStore.penetrable, (value) => {
appWindow.setIgnoreCursorEvents(value)
}, { immediate: true })
watch(() => catStore.alwaysOnTop, setAlwaysOnTop, { immediate: true })
function handleWindowDrag() {
appWindow.startDragging()
}

View File

@@ -48,6 +48,13 @@ function opacityFormatter(value?: number) {
<Switch v-model:checked="catStore.penetrable" />
</ProListItem>
<ProListItem
description="启用后,窗口始终显示在其他应用程序上方"
title="窗口置顶"
>
<Switch v-model:checked="catStore.alwaysOnTop" />
</ProListItem>
<ProListItem
description="将鼠标移动到窗口边缘后,也可以拖动调整窗口尺寸"
title="窗口尺寸"

View File

@@ -8,6 +8,7 @@ type WindowLabel = 'main' | 'preference'
const COMMAND = {
SHOW_WINDOW: 'plugin:custom-window|show_window',
HIDE_WINDOW: 'plugin:custom-window|hide_window',
SET_ALWAYS_ON_TOP: 'plugin:custom-window|set_always_on_top',
}
export function showWindow(label?: WindowLabel) {
@@ -25,3 +26,7 @@ export function hideWindow(label?: WindowLabel) {
invoke(COMMAND.HIDE_WINDOW)
}
}
export function setAlwaysOnTop(alwaysOnTop: boolean) {
invoke(COMMAND.SET_ALWAYS_ON_TOP, { alwaysOnTop })
}

View File

@@ -7,6 +7,7 @@ export const useCatStore = defineStore('cat', () => {
const singleMode = ref(false)
const mouseMirror = ref(false)
const penetrable = ref(false)
const alwaysOnTop = ref(true)
const scale = ref(100)
const opacity = ref(100)
@@ -16,6 +17,7 @@ export const useCatStore = defineStore('cat', () => {
singleMode,
mouseMirror,
penetrable,
alwaysOnTop,
scale,
opacity,
}