objc2_app_kit/lib.rs
1//! # Bindings to the `AppKit` framework
2//!
3//! See [Apple's docs][apple-doc] and [the general docs on framework crates][framework-crates] for more information.
4//!
5//! [apple-doc]: https://developer.apple.com/documentation/appkit/
6//! [framework-crates]: https://docs.rs/objc2/latest/objc2/topics/about_generated/index.html
7//!
8//! Note that a lot of functionality in AppKit requires that the application
9//! has initialized properly, which is only done after the application
10//! delegate has received `applicationDidFinishLaunching`.
11//!
12//! You should aspire to do all your UI initialization work in there!
13//!
14//!
15//! ## NSWindow
16//!
17//! Be careful when creating `NSWindow` if it's not inside a window
18//! controller; in those cases you're _required_ to call
19//! `window.releasedWhenClosed(false)` to get correct memory management, which
20//! is also why the creation methods for `NSWindow` are `unsafe`.
21//!
22//!
23//! ## Examples
24//!
25//! Implementing `NSApplicationDelegate` for a custom class.
26//!
27//! ```ignore
28#![doc = include_str!("../examples/delegate.rs")]
29//! ```
30//!
31//! An example showing basic and a bit more advanced usage of `NSPasteboard`.
32//!
33//! ```ignore
34#![doc = include_str!("../examples/nspasteboard.rs")]
35//! ```
36#![no_std]
37#![cfg_attr(docsrs, feature(doc_auto_cfg))]
38// Update in Cargo.toml as well.
39#![doc(html_root_url = "https://docs.rs/objc2-app-kit/0.3.1")]
40#![recursion_limit = "512"]
41#![allow(non_snake_case)]
42#![allow(unused_imports)]
43#![allow(unreachable_pub)]
44
45#[cfg(feature = "alloc")]
46extern crate alloc;
47
48#[cfg(feature = "std")]
49extern crate std;
50
51#[cfg_attr(feature = "gnustep-1-7", link(name = "gnustep-gui", kind = "dylib"))]
52extern "C" {}
53
54/// (!TARGET_CPU_X86_64 || (TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST))
55///
56/// <https://github.com/xamarin/xamarin-macios/issues/12111>
57// TODO: Make this work with mac catalyst
58#[allow(dead_code)]
59pub(crate) const TARGET_ABI_USES_IOS_VALUES: bool =
60 !cfg!(any(target_arch = "x86", target_arch = "x86_64")) || cfg!(not(target_os = "macos"));
61
62#[cfg(feature = "NSApplication")]
63mod application;
64mod generated;
65#[cfg(feature = "NSImage")]
66mod image;
67#[cfg(feature = "NSText")]
68mod text;
69
70#[cfg(feature = "NSApplication")]
71#[cfg(feature = "NSResponder")]
72pub use self::application::*;
73pub use self::generated::*;
74#[cfg(feature = "NSImage")]
75pub use self::image::*;
76#[cfg(feature = "NSText")]
77pub use self::text::*;
78
79// MacTypes.h
80#[allow(unused)]
81pub(crate) type UTF32Char = u32; // Or maybe Rust's char?
82
83// TODO: Send + Sync for NSColor. Documentation says:
84// > Color objects are immutable and thread-safe
85//
86// But unsure if this applies for things like `-setFill`?
87
88// TODO: Send + Sync for NSCursor. It is immutable, stated here:
89// https://developer.apple.com/documentation/appkit/nscursor/1527062-image?language=objc
90//
91// But unsure if `push`/`pop` methods are safe from non-main threads?
92
93// NOTE: NSEvent is immutable, so it _may_ be possible to make Send + Sync,
94// but let's refrain from doing so, because of:
95// > Safely handled only on the same thread, whether that be the main
96// > thread or a secondary thread; otherwise you run the risk of having
97// > events get out of sequence.
98//
99// <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CocoaFundamentals/AddingBehaviortoaCocoaProgram/AddingBehaviorCocoa.html#//apple_ref/doc/uid/TP40002974-CH5-SW47>
100// <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-123383>
101
102// NOTE: `NSShadow` is marked as `@unchecked Swift.Sendable` in
103// `AppKit.Framework/Modules/AppKit.swiftmodule/*.swiftinterface`, but
104// only when the deployment target is macOS 14.0 (so we can only do that too
105// when https://github.com/rust-lang/rfcs/pull/3750 lands).
106
107#[cfg(test)]
108mod tests {
109 #[test]
110 #[cfg(feature = "NSAccessibilityProtocols")]
111 fn accessibility_element_protocol() {
112 use crate::NSAccessibilityElementProtocol;
113 use objc2::ProtocolType;
114 let actual = <dyn NSAccessibilityElementProtocol>::NAME;
115 assert_eq!(actual, "NSAccessibilityElement");
116 }
117}