#[cfg(all(target_os = "macos", feature = "cocoa-legacy", not(feature = "mini")))]
fn main() {
std::process::exit(run());
}
#[cfg(not(all(target_os = "macos", feature = "cocoa-legacy", not(feature = "mini"))))]
fn main() {
println!(
"apple_appkit_probe: skipped (needs macOS, the `cocoa-legacy` feature, and no `mini` profile)"
);
}
#[cfg(all(target_os = "macos", feature = "cocoa-legacy", not(feature = "mini")))]
fn run() -> i32 {
use cocoa::base::{id, nil};
use cocoa::foundation::NSRect;
use objc::{class, msg_send, sel, sel_impl};
use rust_widgets::platform::{get_platform, Platform};
let mut failures: Vec<String> = Vec::new();
let mut check = |name: &str, ok: bool, detail: String| {
let status = if ok { "PASS" } else { "FAIL" };
println!("[{status}] {name}: {detail}");
if !ok {
failures.push(name.to_string());
}
};
const TOTAL_CHECKS: usize = 12;
let platform = get_platform();
let backend = platform.backend_name();
println!("backend = {backend}");
let on_main_thread: bool = unsafe { msg_send![class!(NSThread), isMainThread] };
check("main_thread", on_main_thread, format!("+[NSThread isMainThread] = {on_main_thread}"));
platform.init();
let app: id = unsafe { msg_send![class!(NSApplication), sharedApplication] };
check("ns_application", app != nil, format!("NSApplication::sharedApplication = {app:p}"));
let window = Platform::create_window(platform, "appkit-probe", 40, 40, 480, 320);
check("create_window_id", window != 0, format!("window id = {window}"));
let windows: id = if app == nil {
nil
} else {
unsafe { msg_send![app, windows] }
};
let window_count: usize = if windows == nil {
0
} else {
unsafe { msg_send![windows, count] }
};
check(
"native_window_registered",
window_count >= 1,
format!("NSApplication.windows.count = {window_count}"),
);
let button = Platform::create_button(platform, window, "Click", 20, 20, 120, 32);
let label = Platform::create_label(platform, window, "Label", 20, 70, 200, 24);
let edit = Platform::create_line_edit(platform, window, "edit", 20, 110, 200, 24);
check(
"native_children",
button != 0 && label != 0 && edit != 0,
format!("button={button} label={label} line_edit={edit}"),
);
Platform::set_widget_text(platform, button, "Clicked");
let button_text = Platform::get_widget_text(platform, button);
check(
"widget_text_roundtrip",
button_text == "Clicked",
format!("get_widget_text = {button_text:?}"),
);
let menu_bar = Platform::create_menu_bar(platform, window, 0, 0, 0, 0);
let file_menu = Platform::create_menu(platform, menu_bar, "File", 0, 0, 0, 0);
let quit_item = Platform::menu_add_item(platform, file_menu, "Quit", Some("q"));
let attached = Platform::attach_menu_bar_to_window(platform, window, menu_bar);
let main_menu: id = if app == nil {
nil
} else {
unsafe { msg_send![app, mainMenu] }
};
check(
"native_menu_bar",
menu_bar != 0 && file_menu != 0 && quit_item != 0 && attached && main_menu != nil,
format!(
"menu_bar={menu_bar} file_menu={file_menu} item={quit_item} attached={attached} mainMenu={main_menu:p}"
),
);
let clip_ok = Platform::set_clipboard_text(platform, "appkit-probe-clip");
let clip_back = Platform::get_clipboard_text(platform);
check(
"native_clipboard",
clip_ok && clip_back == "appkit-probe-clip",
format!("set={clip_ok} get={clip_back:?}"),
);
let alert = Platform::create_message_box(platform, window, "Confirm", "Save?", 0, 0, 300, 120);
let file_dlg = Platform::create_file_dialog(platform, window, 0, 0, 400, 300);
let color_dlg = Platform::create_color_dialog(platform, window, 0, 0, 300, 200);
let font_dlg = Platform::create_font_dialog(platform, window, 0, 0, 300, 200);
let dialogs_ok = alert != 0 && file_dlg != 0 && color_dlg != 0 && font_dlg != 0;
let _ = (alert, file_dlg, color_dlg, font_dlg);
check(
"native_dialog_kinds",
dialogs_ok,
format!("alert={alert} file={file_dlg} color={color_dlg} font={font_dlg}"),
);
Platform::set_widget_geometry(platform, window, 60, 70, 400, 300);
let window_frame_ok: bool = if windows == nil {
false
} else {
let first: id = unsafe { msg_send![windows, firstObject] };
if first == nil {
false
} else {
let frame: NSRect = unsafe { msg_send![first, frame] };
(frame.size.width - 400.0).abs() < 0.5 && (frame.size.height - 300.0).abs() < 0.5
}
};
check(
"native_window_frame_applied",
window_frame_ok,
format!("NSWindow frame updated to 400x300 = {window_frame_ok}"),
);
Platform::hide_widget(platform, window);
let visible_after_hide: bool = if windows == nil {
false
} else {
let first: id = unsafe { msg_send![windows, firstObject] };
if first == nil {
false
} else {
let v: bool = unsafe { msg_send![first, isVisible] };
v
}
};
Platform::show_widget(platform, window);
let visible_after_show: bool = if windows == nil {
false
} else {
let first: id = unsafe { msg_send![windows, firstObject] };
if first == nil {
false
} else {
let v: bool = unsafe { msg_send![first, isVisible] };
v
}
};
check(
"native_window_visibility",
!visible_after_hide && visible_after_show,
format!("after_hide={visible_after_hide} after_show={visible_after_show}"),
);
Platform::set_widget_geometry(platform, button, 30, 30, 140, 36);
Platform::hide_widget(platform, button);
let hidden = !Platform::is_widget_visible(platform, button);
Platform::show_widget(platform, button);
let shown = Platform::is_widget_visible(platform, button);
check(
"visibility_roundtrip",
hidden && shown,
format!("hidden_reported={hidden} shown_reported={shown}"),
);
std::thread::sleep(std::time::Duration::from_millis(50));
if failures.is_empty() {
println!("\nRESULT: PASS ({TOTAL_CHECKS} named checks, backend={backend})");
0
} else {
println!("\nRESULT: FAIL — {}", failures.join(", "));
1
}
}