use bevy::ecs::system::NonSendMarker;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use bevy::winit::WINIT_WINDOWS;
use objc2::rc::Retained;
use objc2_app_kit::NSView;
use objc2_app_kit::NSWindow;
use objc2_app_kit::NSWindowTabbingMode;
use raw_window_handle::HasWindowHandle;
use raw_window_handle::RawWindowHandle;
use super::ManagedWindow;
use super::systems;
fn get_ns_window(entity: Entity) -> Option<Retained<NSWindow>> {
WINIT_WINDOWS.with(|ww| {
let ww = ww.borrow();
let winit_window = ww.get_window(entity)?;
let handle = winit_window.window_handle().ok()?;
let RawWindowHandle::AppKit(appkit_handle) = handle.as_raw() else {
return None;
};
let ns_view: &NSView = unsafe { appkit_handle.ns_view.cast().as_ref() };
ns_view.window()
})
}
fn disable_tabbing_on_primary(
window_entity: Single<Entity, With<PrimaryWindow>>,
_non_send: NonSendMarker,
) {
let Some(ns_window) = get_ns_window(*window_entity) else {
warn!("[macos_tabbing_fix] Could not get NSWindow for primary window");
return;
};
ns_window.setTabbingMode(NSWindowTabbingMode::Disallowed);
debug!("[macos_tabbing_fix] Disabled tabbing on primary window");
}
fn disable_tabbing_on_managed(
new_windows: Query<Entity, Added<ManagedWindow>>,
_non_send: NonSendMarker,
) {
for entity in &new_windows {
let Some(ns_window) = get_ns_window(entity) else {
debug!("[macos_tabbing_fix] Could not get NSWindow for managed window {entity:?}");
continue;
};
ns_window.setTabbingMode(NSWindowTabbingMode::Disallowed);
debug!("[macos_tabbing_fix] Disabled tabbing on managed window {entity:?}");
}
}
pub(crate) fn init(app: &mut App) {
app.add_systems(Startup, disable_tabbing_on_primary);
app.add_systems(
Update,
disable_tabbing_on_managed.before(systems::restore_windows),
);
}