tenseleyflow/claudex / 3efbb56

Browse files

fix: start-dragging permission + re-center window on monitor disconnect

Authored by espadonne
SHA
3efbb566947cbd19ab70170605dde1fde77b50fc
Parents
eb1c4c1
Tree
f850011

2 changed files

StatusFile+-
M src-tauri/capabilities/default.json 6 1
M src-tauri/src/lib.rs 44 7
src-tauri/capabilities/default.jsonmodified
@@ -4,6 +4,11 @@
44
   "description": "Default window capabilities for claudex.",
55
   "windows": ["main"],
66
   "permissions": [
7
-    "core:default"
7
+    "core:default",
8
+    "core:window:allow-start-dragging",
9
+    "core:window:allow-set-focus",
10
+    "core:window:allow-center",
11
+    "core:window:allow-set-position",
12
+    "core:window:allow-outer-position"
813
   ]
914
 }
src-tauri/src/lib.rsmodified
@@ -80,14 +80,51 @@ pub fn run() {
8080
             Ok(())
8181
         })
8282
         .on_window_event(|window, event| {
83
-            if let tauri::WindowEvent::Destroyed = event {
84
-                // Best-effort cache flush + reap every live PTY so
85
-                // we don't leave zombie claude subprocesses running
86
-                // after a hard app quit.
87
-                if let Some(state) = window.app_handle().try_state::<commands::AppState>() {
88
-                    commands::persist_cache_on_exit(&state);
89
-                    commands::shutdown_active_ptys(&state);
83
+            match event {
84
+                tauri::WindowEvent::Destroyed => {
85
+                    // Best-effort cache flush + reap every live PTY so
86
+                    // we don't leave zombie claude subprocesses running
87
+                    // after a hard app quit.
88
+                    if let Some(state) =
89
+                        window.app_handle().try_state::<commands::AppState>()
90
+                    {
91
+                        commands::persist_cache_on_exit(&state);
92
+                        commands::shutdown_active_ptys(&state);
93
+                    }
9094
                 }
95
+                tauri::WindowEvent::Resized(_) => {
96
+                    // macOS moves the window when an external monitor
97
+                    // disconnects. If the new position is fully
98
+                    // off-screen the user can't see it. Re-center as
99
+                    // a safety net.
100
+                    if let Ok(pos) = window.outer_position() {
101
+                        if let Ok(size) = window.outer_size() {
102
+                            // Heuristic: if the window's left+width or
103
+                            // top+height places it entirely off-screen
104
+                            // (negative right edge or top below a
105
+                            // reasonable bound), re-center it. We
106
+                            // can't easily enumerate monitors from
107
+                            // Tauri, so check against reasonable
108
+                            // bounds: right edge < 0 OR left edge >
109
+                            // 6000 OR top edge > 4000 OR bottom < 0.
110
+                            let right = pos.x + size.width as i32;
111
+                            let bottom = pos.y + size.height as i32;
112
+                            if right < 0
113
+                                || pos.x > 6000
114
+                                || bottom < 0
115
+                                || pos.y > 4000
116
+                            {
117
+                                tracing::info!(
118
+                                    x = pos.x,
119
+                                    y = pos.y,
120
+                                    "window off-screen after resize, re-centering"
121
+                                );
122
+                                let _ = window.center();
123
+                            }
124
+                        }
125
+                    }
126
+                }
127
+                _ => {}
91128
             }
92129
         })
93130
         .invoke_handler(tauri::generate_handler![