fix(window): stop the app panicking when windows close and open together (#2124)

Closing a window posts its full-screen notification while the runtime still
holds its window table; the title bar observer emitted from there and the emit
re-entered the table ("RefCell already mutably borrowed"). The emit now goes
out after the notification returns.

Opening several project windows at once could also hand the same project-N
label to each request, so label choice and window creation now take turns.

Co-authored-by: Claude <[email protected]>
Цей коміт міститься в:
l0ng-aiтаClaude authored and GitHub committed 2026-11-08 17:46:10 +08:00
1 джерело f6e942dd00
коміт 4d968a2aca
2 files changed
+12 -1

No files matched your search

+6 -1
Переглянути файл
@@ -89,7 +89,12 @@ fn track(window: &NSWindow, app: &tauri::AppHandle) -> Tracked {
crate::macos::hide_tab_bar(&window);
}
// The web title bar releases the room kept for the window buttons in full screen.
app.state::<crate::state::AppState>().sink.emit(ide_core::IdeEvent::WindowFullscreenChanged);
// Closing a window posts this while the runtime still holds its window table, and an
// emit from here evaluates script in that table; send it from outside the notification.
let app = app.clone();
tauri::async_runtime::spawn(async move {
app.state::<crate::state::AppState>().sink.emit(ide_core::IdeEvent::WindowFullscreenChanged);
});
});
let observer = unsafe {
NSNotificationCenter::defaultCenter().addObserverForName_object_queue_usingBlock(
+6
Переглянути файл
@@ -286,6 +286,9 @@ pub fn settings_label(parent: &str) -> String {
format!("{}-{parent}", AuxKind::Settings.name())
}
/// Held from choosing a project window's label until the window exists.
static CREATING: Mutex<()> = Mutex::new(());
/// Windows being built to join a window group, which takes their frame from the group.
#[cfg(target_os = "macos")]
static JOINING_GROUP: Mutex<Vec<String>> = Mutex::new(Vec::new());
@@ -665,6 +668,8 @@ fn create_window_for(
) -> IdeResult<WebviewWindow> {
#[cfg(target_os = "macos")]
let tab_target = if _restoring { None } else { crate::macos::new_project_tab_target(app, &launch)? };
// The label is free only until the window exists, so concurrent opens take turns.
let creating = CREATING.lock();
let windows = app.webview_windows();
let label = next_label(windows.keys().map(String::as_str));
let mut config = window_config(app)?;
@@ -691,6 +696,7 @@ fn create_window_for(
config.visible = false;
}
let window = build_project_window(app, config);
drop(creating);
// Plugins hear of the window from the main thread's queue; forget it after them.
#[cfg(target_os = "macos")]
if tab_target.is_some() {