core-foundation-rs

repository·main·Indexed 22 days ago

https://github.com/servo/core-foundation-rs

A collection of Rust bindings for Apple's Core Foundation, Core Graphics, Core Text, and related frameworks. It provides safe and idiomatic access to macOS system APIs, including low-level FFI bindings via core-foundation-sys and interfaces for Core Animation (CALayer, CARenderer, CATransform3D) and Core Foundation types like CFBag. Note that the cocoa and cocoa-foundation crates within this repository are deprecated in favor of objc2 and objc2-foundation.

Tokens
34K
Snippets
60
Records
194
Agent score
79%

What's inside core-foundation-rs

  1. Configure macOS version compatibility

    main

    By default, core-foundation-rs targets macOS 10.7. You can adjust the target version using Cargo features:

    • macOS 10.8+ features: Enable the mac_os_10_8_features feature.
    • Hybrid 10.7/10.8 support: To use 10.8 features while maintaining 10.7 compatibility, enable both mac_os_10_8_features and mac_os_10_7_support.

    Note: Enabling both features requires weak linkage, which is a nightly-only feature in Rust (as of version 1.19).

  2. Use the core-text crate

    main

    The core_text crate provides Rust bindings to Apple's Core Text framework. It is organized into several modules that handle font management, text layout (frames, lines, runs), and string attributes.

    Important Memory Management Note: Many functions in this crate add objects to the Objective-C autorelease pool. If your application does not have an active autorelease pool, using these functions will cause memory leaks. Ensure you are running within an environment that manages autorelease pools (like a standard Cocoa application loop) or manually manage pools where necessary.

  3. Use the core-graphics crate

    main
    The core-graphics crate provides Rust bindings to Apple's Core Graphics framework. It is organized into several modules covering different aspects of graphics programming. Note that some modules (like access, display, event, event_source, and window) are only available when targeting macOS.
  4. How to upcast and downcast `CFPropertyList` subclasses

    main

    The CFPropertyList type acts as a superclass for several specific types: CFData, CFString, CFArray, CFDictionary, CFDate, CFBoolean, and CFNumber.

    Upcasting

    To treat a specific type as a generic property list, use the CFPropertyListSubClass trait methods:

    • to_CFPropertyList(): Creates a new CFPropertyList instance by incrementing the reference count (Get Rule).
    • into_CFPropertyList(): Consumes the original object and transfers ownership to a CFPropertyList without changing the reference count (Create Rule).

    Downcasting

    If you have a CFPropertyList and want to recover its specific type, use:

    • downcast<T>(): Returns an Option<T> by incrementing the reference count if the type matches.
    • downcast_into<T>(): Consumes the CFPropertyList and returns Option<T> without touching the reference count.
  5. Manage font collections with CTFontCollection

    main

    The CTFontCollection type represents a collection of fonts. You can create collections from specific descriptors, from all available fonts on the system, or filtered by a specific font family. Once you have a collection, you can retrieve its constituent font descriptors.

    Key operations:

    • Create from descriptors: Use new_from_descriptors to build a collection from an existing CFArray of CTFontDescriptor objects. This supports a kCTFontCollectionRemoveDuplicatesOption to ensure uniqueness.
    • Create from all system fonts: Use create_for_all_families to get a collection containing all fonts available on the system.
    • Create for a specific family: Use create_for_family to create a collection containing only fonts belonging to a specific family name (e.g., "Helvetica").
    • Retrieve descriptors: Call .get_descriptors() on a CTFontCollection instance to get a CFArray of CTFontDescriptor objects.
  6. Convert between CFDictionary and CFMutableDictionary

    main

    You can transition between immutable and mutable dictionary types:

    1. Immutable to Mutable:

      • Use CFMutableDictionary::from(&cf_dictionary) to create a new mutable copy.
      • Use unsafe { cf_dictionary.to_mutable() } to get a mutable view of the same underlying dictionary (only if the underlying dictionary was originally mutable).
    2. Mutable to Immutable:

      • Use cf_mutable_dictionary.to_immutable() to get an immutable view of the same dictionary.
    3. Untyped conversion:

      • to_untyped(): Returns a dictionary with types reset to *const c_void (increments retain count).
      • into_untyped(): Consumes the dictionary and returns an untyped version without incrementing the retain count (faster).
  7. Handle display reconfiguration callbacks

    main

    You can register a callback to be notified whenever the display configuration changes (e.g., a monitor is plugged in, a display is moved, or mirroring starts/stops).

    Callback Signature: unsafe extern "C" fn(display: CGDirectDisplayID, flags: u32, user_info: *const c_void)

    CGDisplayChangeSummaryFlags (passed in flags):

    • kCGDisplayBeginConfigurationFlag: Configuration is starting.
    • kCGDisplayMovedFlag: Display position in global space changed.
    • kCGDisplaySetMainFlag: Display became the main display.
    • kCGDisplaySetModeFlag: Display mode changed.
    • kCGDisplayAddFlag: Display added to active list.
    • kCGDisplayRemoveFlag: Display removed from active list.
    • kCGDisplayEnabledFlag: Display enabled.
    • kCGDisplayDisabledFlag: Display disabled.
    • kCGDisplayMirrorFlag: Display is now mirroring.
    • kCGDisplayUnMirrorFlag: Display stopped mirroring.
    • kCGDisplayDesktopShapeChangedFlag: The union of display areas changed.
  8. Configure display settings using a configuration session

    main

    To change display settings (like mode, origin, or mirroring), you must follow a transactional pattern:

    1. Begin a configuration session with begin_configuration() to get a CGDisplayConfigRef.
    2. Apply changes (e.g., configure_display_with_display_mode, configure_display_origin, or configure_display_mirror_of_display) using the configuration reference.
    3. Commit the changes using complete_configuration(config_ref, option).

    If something goes wrong, use cancel_configuration(config_ref) to abort the changes.

    CGConfigureOption values:

    • ConfigureForAppOnly: Changes apply only to the current application.
    • ConfigureForSession: Changes apply to the current user session.
    • ConfigurePermanently: Changes are saved permanently.
  9. How CFArray works as a heterogeneous immutable array

    main

    A CFArray is a Core Foundation abstraction for an immutable, heterogeneous array. In core-foundation-rs, it is wrapped in a type-safe CFArray<T> struct.

    Key Concepts

    • Immutability: Once created, the array cannot be modified. To 'change' an array, you must create a new one.
    • Type Safety: While the underlying Core Foundation array is heterogeneous (can hold any type), the Rust wrapper uses a phantom type T to provide type-safe access via ItemRef<'_, T>.
    • Memory Management: The CFArray wrapper implements Drop to automatically call CFRelease when the object goes out of scope, following the Core Foundation 'Create Rule'.
    • Conversion: You can transition between typed (CFArray<T>) and untyped (CFArray) states using to_untyped() or into_untyped() depending on whether you need to preserve the original instance.
  10. Use `ItemRef` and `ItemMutRef` for container elements

    main

    When working with containers, the library provides ItemRef (for immutable access) and ItemMutRef (for mutable access) to represent references to elements inside a container. These types wrap the underlying data using ManuallyDrop to manage lifetimes safely.

    They implement Deref and DerefMut respectively, allowing you to treat them like the underlying type.

  11. How the `TCFType` trait works

    main

    The TCFType trait is the foundation of the library. Almost all Core Foundation types implement this trait. It provides a unified interface for interacting with Core Foundation objects, including:

    • Type Identity: Check if an object is an instance of a type using instance_of::<T>() or get its type_id().
    • Reference Management: Convert between wrapped types and raw TypeRefs using as_CFTypeRef(), as_CFType(), or into_CFType().
    • Metadata: Retrieve the object's retain_count() or type_of() ID.
    • Debugging: Use show() to write a debugging version of the object to standard error.