Skip to content

Commit 649362e

Browse files
committed
Merge feat/app-bar: custom app bar for standalone mode
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> # Conflicts: # standalone/src-tauri/Cargo.lock
2 parents 234f5f6 + 7460880 commit 649362e

11 files changed

Lines changed: 422 additions & 4 deletions

File tree

lib/src/components/Pond.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,30 @@ export function Pond({
16881688
const handleReattachRef = useRef(handleReattach);
16891689
handleReattachRef.current = handleReattach;
16901690

1691+
// Listen for external "new terminal" requests (e.g. from the standalone AppBar)
1692+
useEffect(() => {
1693+
const handler = () => {
1694+
const api = apiRef.current;
1695+
if (!api) return;
1696+
const newId = generatePaneId();
1697+
const active = api.activePanel;
1698+
let direction: 'right' | 'below' = 'right';
1699+
if (active) {
1700+
direction = (active.api.width - active.api.height > 0) ? 'right' : 'below';
1701+
}
1702+
api.addPanel({
1703+
id: newId,
1704+
component: 'terminal',
1705+
tabComponent: 'terminal',
1706+
title: '<unnamed>',
1707+
position: active ? { referencePanel: active.id, direction } : undefined,
1708+
});
1709+
selectPanel(newId);
1710+
};
1711+
window.addEventListener('mouseterm:new-terminal', handler);
1712+
return () => window.removeEventListener('mouseterm:new-terminal', handler);
1713+
}, [generatePaneId, selectPanel]);
1714+
16911715
const addSplitPanel = useCallback((
16921716
id: string | null,
16931717
direction: 'right' | 'below',

standalone/src-tauri/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

standalone/src-tauri/capabilities/default.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
"windows": ["main"],
55
"permissions": [
66
"core:default",
7+
"core:window:allow-minimize",
8+
"core:window:allow-toggle-maximize",
9+
"core:window:allow-close",
10+
"core:window:allow-is-maximized",
11+
"core:window:allow-start-dragging",
712
"shell:allow-spawn",
813
"shell:allow-stdin-write",
914
"shell:allow-kill",

standalone/src-tauri/gen/schemas/acl-manifests.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"default":{"identifier":"default","description":"Default capability set for MouseTerm","local":true,"windows":["main"],"permissions":["core:default","shell:allow-spawn","shell:allow-stdin-write","shell:allow-kill"]}}
1+
{"default":{"identifier":"default","description":"Default capability set for MouseTerm","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-minimize","core:window:allow-toggle-maximize","core:window:allow-close","core:window:allow-is-maximized","core:window:allow-start-dragging","shell:allow-spawn","shell:allow-stdin-write","shell:allow-kill","shell:allow-open"]}}

standalone/src-tauri/gen/schemas/desktop-schema.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,60 @@
24192419
"type": "string",
24202420
"const": "shell:deny-stdin-write",
24212421
"markdownDescription": "Denies the stdin_write command without any pre-configured scope."
2422+
},
2423+
{
2424+
"description": "This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n\n#### This default permission set includes:\n\n- `allow-check`\n- `allow-download`\n- `allow-install`\n- `allow-download-and-install`",
2425+
"type": "string",
2426+
"const": "updater:default",
2427+
"markdownDescription": "This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n\n#### This default permission set includes:\n\n- `allow-check`\n- `allow-download`\n- `allow-install`\n- `allow-download-and-install`"
2428+
},
2429+
{
2430+
"description": "Enables the check command without any pre-configured scope.",
2431+
"type": "string",
2432+
"const": "updater:allow-check",
2433+
"markdownDescription": "Enables the check command without any pre-configured scope."
2434+
},
2435+
{
2436+
"description": "Enables the download command without any pre-configured scope.",
2437+
"type": "string",
2438+
"const": "updater:allow-download",
2439+
"markdownDescription": "Enables the download command without any pre-configured scope."
2440+
},
2441+
{
2442+
"description": "Enables the download_and_install command without any pre-configured scope.",
2443+
"type": "string",
2444+
"const": "updater:allow-download-and-install",
2445+
"markdownDescription": "Enables the download_and_install command without any pre-configured scope."
2446+
},
2447+
{
2448+
"description": "Enables the install command without any pre-configured scope.",
2449+
"type": "string",
2450+
"const": "updater:allow-install",
2451+
"markdownDescription": "Enables the install command without any pre-configured scope."
2452+
},
2453+
{
2454+
"description": "Denies the check command without any pre-configured scope.",
2455+
"type": "string",
2456+
"const": "updater:deny-check",
2457+
"markdownDescription": "Denies the check command without any pre-configured scope."
2458+
},
2459+
{
2460+
"description": "Denies the download command without any pre-configured scope.",
2461+
"type": "string",
2462+
"const": "updater:deny-download",
2463+
"markdownDescription": "Denies the download command without any pre-configured scope."
2464+
},
2465+
{
2466+
"description": "Denies the download_and_install command without any pre-configured scope.",
2467+
"type": "string",
2468+
"const": "updater:deny-download-and-install",
2469+
"markdownDescription": "Denies the download_and_install command without any pre-configured scope."
2470+
},
2471+
{
2472+
"description": "Denies the install command without any pre-configured scope.",
2473+
"type": "string",
2474+
"const": "updater:deny-install",
2475+
"markdownDescription": "Denies the install command without any pre-configured scope."
24222476
}
24232477
]
24242478
},

standalone/src-tauri/gen/schemas/macOS-schema.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,60 @@
24192419
"type": "string",
24202420
"const": "shell:deny-stdin-write",
24212421
"markdownDescription": "Denies the stdin_write command without any pre-configured scope."
2422+
},
2423+
{
2424+
"description": "This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n\n#### This default permission set includes:\n\n- `allow-check`\n- `allow-download`\n- `allow-install`\n- `allow-download-and-install`",
2425+
"type": "string",
2426+
"const": "updater:default",
2427+
"markdownDescription": "This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n\n#### This default permission set includes:\n\n- `allow-check`\n- `allow-download`\n- `allow-install`\n- `allow-download-and-install`"
2428+
},
2429+
{
2430+
"description": "Enables the check command without any pre-configured scope.",
2431+
"type": "string",
2432+
"const": "updater:allow-check",
2433+
"markdownDescription": "Enables the check command without any pre-configured scope."
2434+
},
2435+
{
2436+
"description": "Enables the download command without any pre-configured scope.",
2437+
"type": "string",
2438+
"const": "updater:allow-download",
2439+
"markdownDescription": "Enables the download command without any pre-configured scope."
2440+
},
2441+
{
2442+
"description": "Enables the download_and_install command without any pre-configured scope.",
2443+
"type": "string",
2444+
"const": "updater:allow-download-and-install",
2445+
"markdownDescription": "Enables the download_and_install command without any pre-configured scope."
2446+
},
2447+
{
2448+
"description": "Enables the install command without any pre-configured scope.",
2449+
"type": "string",
2450+
"const": "updater:allow-install",
2451+
"markdownDescription": "Enables the install command without any pre-configured scope."
2452+
},
2453+
{
2454+
"description": "Denies the check command without any pre-configured scope.",
2455+
"type": "string",
2456+
"const": "updater:deny-check",
2457+
"markdownDescription": "Denies the check command without any pre-configured scope."
2458+
},
2459+
{
2460+
"description": "Denies the download command without any pre-configured scope.",
2461+
"type": "string",
2462+
"const": "updater:deny-download",
2463+
"markdownDescription": "Denies the download command without any pre-configured scope."
2464+
},
2465+
{
2466+
"description": "Denies the download_and_install command without any pre-configured scope.",
2467+
"type": "string",
2468+
"const": "updater:deny-download-and-install",
2469+
"markdownDescription": "Denies the download_and_install command without any pre-configured scope."
2470+
},
2471+
{
2472+
"description": "Denies the install command without any pre-configured scope.",
2473+
"type": "string",
2474+
"const": "updater:deny-install",
2475+
"markdownDescription": "Denies the install command without any pre-configured scope."
24222476
}
24232477
]
24242478
},

standalone/src-tauri/src/lib.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,38 @@ fn shutdown_sidecar(state: tauri::State<'_, SidecarState>) {
144144
let _ = state.tx.send(SidecarMsg::Shutdown);
145145
}
146146

147+
#[tauri::command]
148+
fn get_project_dir() -> String {
149+
std::env::var("HOME")
150+
.or_else(|_| std::env::var("USERPROFILE"))
151+
.unwrap_or_default()
152+
}
153+
154+
#[derive(Serialize, Clone)]
155+
struct ShellInfo {
156+
name: String,
157+
path: String,
158+
}
159+
160+
#[tauri::command]
161+
fn get_default_shell() -> ShellInfo {
162+
#[cfg(target_os = "windows")]
163+
let shell_path = std::env::var("ComSpec")
164+
.or_else(|_| std::env::var("COMSPEC"))
165+
.unwrap_or_else(|_| String::from("C:\\Windows\\System32\\cmd.exe"));
166+
167+
#[cfg(not(target_os = "windows"))]
168+
let shell_path = std::env::var("SHELL")
169+
.unwrap_or_else(|_| String::from("/bin/sh"));
170+
171+
let name = Path::new(&shell_path)
172+
.file_name()
173+
.map(|n| n.to_string_lossy().into_owned())
174+
.unwrap_or_else(|| shell_path.clone());
175+
176+
ShellInfo { name, path: shell_path }
177+
}
178+
147179
fn resolve_sidecar_path(resource_dir: Option<PathBuf>, manifest_dir: &Path) -> PathBuf {
148180
if let Some(ref dir) = resource_dir {
149181
// Tauri maps `../sidecar` to `_up_/sidecar` when bundling resources
@@ -262,8 +294,24 @@ pub fn run() {
262294
.setup(|app| {
263295
let sidecar_state = start_sidecar(app.handle());
264296
app.manage(sidecar_state);
297+
298+
// On non-macOS, remove native decorations for a fully custom title bar.
299+
// macOS uses titleBarStyle "Overlay" from config instead, which preserves
300+
// rounded corners and native traffic-light buttons.
301+
#[cfg(not(target_os = "macos"))]
302+
{
303+
if let Some(window) = app.get_webview_window("main") {
304+
let _ = window.set_decorations(false);
305+
}
306+
}
307+
265308
Ok(())
266309
})
310+
.on_window_event(|_window, event| {
311+
if let tauri::WindowEvent::CloseRequested { .. } = event {
312+
std::process::exit(0);
313+
}
314+
})
267315
.invoke_handler(tauri::generate_handler![
268316
pty_spawn,
269317
pty_write,
@@ -273,6 +321,8 @@ pub fn run() {
273321
pty_get_scrollback,
274322
pty_request_init,
275323
shutdown_sidecar,
324+
get_project_dir,
325+
get_default_shell,
276326
])
277327
.run(tauri::generate_context!())
278328
.expect("error while running MouseTerm");

standalone/src-tauri/tauri.conf.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
"windows": [
1414
{
1515
"title": "MouseTerm",
16+
"titleBarStyle": "Overlay",
17+
"hiddenTitle": true,
1618
"width": 1200,
1719
"height": 800,
1820
"minWidth": 800,

0 commit comments

Comments
 (0)