Rust global shortcuts (Ctrl+1-5) now emit a pip:open event instead of creating windows directly, so geometry restore, loading spinner and state tracking all work regardless of how the PiP is opened.
130 lines
4.9 KiB
Rust
130 lines
4.9 KiB
Rust
use tauri::{
|
|
menu::{Menu, MenuItem},
|
|
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
|
|
Emitter, Manager, WindowEvent,
|
|
};
|
|
use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState};
|
|
|
|
fn show_main_window(app: &tauri::AppHandle) {
|
|
if let Some(window) = app.get_webview_window("main") {
|
|
let _ = window.show();
|
|
let _ = window.unminimize();
|
|
let _ = window.set_focus();
|
|
}
|
|
}
|
|
|
|
fn open_pip_terminal(app: &tauri::AppHandle, idx: u8) {
|
|
let label = format!("pip-terminal-{}", idx);
|
|
|
|
// If PiP already exists, just focus it
|
|
if let Some(win) = app.get_webview_window(&label) {
|
|
let _ = win.set_focus();
|
|
return;
|
|
}
|
|
|
|
// Delegate creation to frontend (handles geometry restore, loading spinner, state tracking)
|
|
let _ = app.emit("pip:open", idx);
|
|
}
|
|
|
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
pub fn run() {
|
|
tauri::Builder::default()
|
|
.plugin(tauri_plugin_http::init())
|
|
.plugin(tauri_plugin_store::Builder::new().build())
|
|
.plugin(tauri_plugin_notification::init())
|
|
.plugin(tauri_plugin_clipboard_manager::init())
|
|
.plugin(tauri_plugin_dialog::init())
|
|
.plugin(
|
|
tauri_plugin_global_shortcut::Builder::new()
|
|
.with_handler(|app, shortcut, event| {
|
|
if event.state != ShortcutState::Pressed {
|
|
return;
|
|
}
|
|
|
|
let mods = shortcut.mods;
|
|
let key = shortcut.key;
|
|
|
|
// Ctrl+Alt+E → show main window
|
|
if mods == Modifiers::CONTROL | Modifiers::ALT && key == Code::KeyE {
|
|
show_main_window(app);
|
|
return;
|
|
}
|
|
|
|
// Ctrl+1-5 → open PiP terminal
|
|
if mods == Modifiers::CONTROL {
|
|
match key {
|
|
Code::Digit1 => open_pip_terminal(app, 1),
|
|
Code::Digit2 => open_pip_terminal(app, 2),
|
|
Code::Digit3 => open_pip_terminal(app, 3),
|
|
Code::Digit4 => open_pip_terminal(app, 4),
|
|
Code::Digit5 => open_pip_terminal(app, 5),
|
|
_ => {}
|
|
}
|
|
}
|
|
})
|
|
.build(),
|
|
)
|
|
.setup(|app| {
|
|
// Register global shortcuts (desktop only)
|
|
#[cfg(desktop)]
|
|
{
|
|
let ctrl_alt = Modifiers::CONTROL | Modifiers::ALT;
|
|
let ctrl = Modifiers::CONTROL;
|
|
let shortcuts = [
|
|
Shortcut::new(Some(ctrl_alt), Code::KeyE),
|
|
Shortcut::new(Some(ctrl), Code::Digit1),
|
|
Shortcut::new(Some(ctrl), Code::Digit2),
|
|
Shortcut::new(Some(ctrl), Code::Digit3),
|
|
Shortcut::new(Some(ctrl), Code::Digit4),
|
|
Shortcut::new(Some(ctrl), Code::Digit5),
|
|
];
|
|
for s in &shortcuts {
|
|
let _ = app.global_shortcut().register(*s);
|
|
}
|
|
}
|
|
|
|
// Build system tray (desktop only)
|
|
#[cfg(desktop)]
|
|
{
|
|
let show_item = MenuItem::with_id(app, "show", "Show", true, None::<&str>)?;
|
|
let quit_item = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
|
|
let menu = Menu::with_items(app, &[&show_item, &quit_item])?;
|
|
|
|
TrayIconBuilder::new()
|
|
.icon(app.default_window_icon().unwrap().clone())
|
|
.menu(&menu)
|
|
.show_menu_on_left_click(false)
|
|
.on_menu_event(|app, event| match event.id.as_ref() {
|
|
"show" => show_main_window(app),
|
|
"quit" => app.exit(0),
|
|
_ => {}
|
|
})
|
|
.on_tray_icon_event(|tray, event| {
|
|
if let TrayIconEvent::Click {
|
|
button: MouseButton::Left,
|
|
button_state: MouseButtonState::Up,
|
|
..
|
|
} = event
|
|
{
|
|
show_main_window(tray.app_handle());
|
|
}
|
|
})
|
|
.build(app)?;
|
|
}
|
|
|
|
Ok(())
|
|
})
|
|
.on_window_event(|window, event| {
|
|
// Hide main window to tray instead of closing (desktop only)
|
|
#[cfg(desktop)]
|
|
if let WindowEvent::CloseRequested { api, .. } = event {
|
|
if window.label() == "main" {
|
|
api.prevent_close();
|
|
let _ = window.hide();
|
|
}
|
|
}
|
|
})
|
|
.run(tauri::generate_context!())
|
|
.expect("error while running tauri application");
|
|
}
|