дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-08 19:02:17 +02:00
Merge remote-tracking branch 'origin/main' into fix/cli-launcher-all-platforms
# Conflicts: # src/platform/locales/text/en.json # src/platform/locales/text/zh.json
Цей коміт міститься в:
коміт
5890e8abc5
51 files changed
+516
-33
No files matched your search
@@ -87,6 +87,7 @@ pub fn builder() -> tauri_specta::Builder<tauri::Wry> {
|
||||
window_group::window_group_close,
|
||||
window_group::window_group_close_tabs,
|
||||
window_group::window_group_cancel_close,
|
||||
window_group::window_group_before_close,
|
||||
window_group::window_group_reorder,
|
||||
window_group::window_group_restore,
|
||||
app::light_edit_open,
|
||||
|
||||
@@ -55,6 +55,20 @@ pub fn window_group_cancel_close(window: WebviewWindow) {
|
||||
groups::cancel_close(window.app_handle(), window.label());
|
||||
}
|
||||
|
||||
/// This window closes next (its prompts passed): a fullscreen group's host first hands its Space
|
||||
/// to the tab that takes over.
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn window_group_before_close(window: WebviewWindow) -> IdeResult<()> {
|
||||
#[cfg(target_os = "macos")]
|
||||
return groups::before_close(window.app_handle(), window.label()).await;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
let _ = window;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn window_group_reorder(window: WebviewWindow, labels: Vec<String>) -> IdeResult<()> {
|
||||
|
||||
@@ -173,6 +173,44 @@ pub fn watch_fullscreen_host(host: &WebviewWindow, left: impl Fn() + Send + 'sta
|
||||
})
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
/// Windows being waited on to finish entering fullscreen.
|
||||
static ENTERING_FULLSCREEN: std::cell::RefCell<std::collections::HashMap<String, FullscreenObserver>> = std::cell::RefCell::default();
|
||||
}
|
||||
|
||||
/// Toggles `window` into native fullscreen and resolves once it is there, or after `timeout`.
|
||||
pub async fn enter_fullscreen_and_wait(window: &WebviewWindow, timeout: std::time::Duration) -> tauri::Result<()> {
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
let label = window.label().to_owned();
|
||||
let target = window.clone();
|
||||
on_main(window, move || unsafe {
|
||||
let Ok(pointer) = target.ns_window() else { return };
|
||||
let native = &*pointer.cast::<NSWindow>();
|
||||
let tx = std::cell::Cell::new(Some(tx));
|
||||
let block = block2::RcBlock::new(move |_| {
|
||||
if let Some(tx) = tx.take() {
|
||||
let _ = tx.send(());
|
||||
}
|
||||
});
|
||||
let observer = NSNotificationCenter::defaultCenter().addObserverForName_object_queue_usingBlock(
|
||||
Some(objc2_app_kit::NSWindowDidEnterFullScreenNotification),
|
||||
Some(native),
|
||||
None,
|
||||
&block,
|
||||
);
|
||||
ENTERING_FULLSCREEN.with_borrow_mut(|waits| waits.insert(label, FullscreenObserver(observer)));
|
||||
})?;
|
||||
let toggled = native_toggle_fullscreen(window);
|
||||
if toggled.is_ok() {
|
||||
let _ = tokio::time::timeout(timeout, rx).await;
|
||||
}
|
||||
let label = window.label().to_owned();
|
||||
on_main(window, move || {
|
||||
ENTERING_FULLSCREEN.with_borrow_mut(|waits| waits.remove(&label));
|
||||
})?;
|
||||
toggled
|
||||
}
|
||||
|
||||
/// An observer on the workspace's notification center, removed when dropped.
|
||||
struct WorkspaceObserver(Retained<NSNotificationCenter>, Retained<ProtocolObject<dyn NSObjectProtocol>>);
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ const FRAME_SETTLE_AFTER_MOVE: Duration = Duration::from_millis(100);
|
||||
/// Longest wait for a closed host's fullscreen Space to go before the next tab takes the screen.
|
||||
#[cfg(target_os = "macos")]
|
||||
const SPACE_TEARDOWN: Duration = Duration::from_millis(1500);
|
||||
/// Longest wait for the tab taking over from a closing host to enter its own fullscreen Space.
|
||||
#[cfg(target_os = "macos")]
|
||||
const SPACE_HANDOVER: Duration = Duration::from_millis(2000);
|
||||
/// Coalesces the move/resize events a drag emits.
|
||||
static FRAME_SYNC_GENERATION: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
@@ -327,6 +330,13 @@ pub fn toggle_fullscreen(window: &WebviewWindow) -> IdeResult<bool> {
|
||||
/// Makes `host` the fullscreen window of its group, or of its own Space when ungrouped.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn host_fullscreen(app: &AppHandle, host: &WebviewWindow) -> IdeResult<()> {
|
||||
prepare_host(app, host)?;
|
||||
crate::macos::native_toggle_fullscreen(host).map_err(|e| IdeError::internal(e.to_string()))
|
||||
}
|
||||
|
||||
/// `host` and the other members of its group, ready for `host` to enter fullscreen.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn prepare_host(app: &AppHandle, host: &WebviewWindow) -> IdeResult<()> {
|
||||
let err = |e: tauri::Error| IdeError::internal(e.to_string());
|
||||
let members = app.state::<WindowsState>().groups.lock().group(host.label()).map(|g| g.members.clone());
|
||||
crate::macos::set_fullscreen_auxiliary(host, None).map_err(err)?;
|
||||
@@ -338,8 +348,29 @@ fn host_fullscreen(app: &AppHandle, host: &WebviewWindow) -> IdeResult<()> {
|
||||
if members.is_some() {
|
||||
watch_host(app, host)?;
|
||||
}
|
||||
host.show().map_err(err)?;
|
||||
crate::macos::native_toggle_fullscreen(host).map_err(err)
|
||||
host.show().map_err(err)
|
||||
}
|
||||
|
||||
/// A fullscreen group's host is about to close, past its prompts. The tab that takes over leaves
|
||||
/// for a Space of its own first, so the screen moves straight to it; were the host closed first,
|
||||
/// its Space would end and show the desktop until the next one opened.
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn before_close(app: &AppHandle, caller: &str) -> IdeResult<()> {
|
||||
let state = app.state::<WindowsState>();
|
||||
let Some(members) = state.groups.lock().group(caller).map(|g| g.members.clone()) else { return Ok(()) };
|
||||
if state.quitting() || fullscreen_host(app, &members).is_none_or(|host| host.label() != caller) {
|
||||
return Ok(());
|
||||
}
|
||||
// Detached now, the closing host leaves nothing for `destroyed` to hand over.
|
||||
let next = state.groups.lock().detach(caller);
|
||||
changed(app);
|
||||
let Some(next) = next.and_then(|label| app.get_webview_window(&label)) else { return Ok(()) };
|
||||
prepare_host(app, &next)?;
|
||||
crate::macos::enter_fullscreen_and_wait(&next, SPACE_HANDOVER)
|
||||
.await
|
||||
.map_err(|e| IdeError::internal(e.to_string()))?;
|
||||
windows::focus(&next);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
||||
Reference in new issue
Заблокувати користувача