pub struct SCContentSharingPicker;Expand description
System UI for selecting content to share
Available on macOS 14.0+
The picker requires user interaction and cannot block the calling thread. Use one of these approaches:
- Callback-based:
show()/show_filter()- pass a callback closure - Async/await:
AsyncSCContentSharingPickerfrom theasync_apimodule
§Example (callback)
use screencapturekit::content_sharing_picker::*;
let config = SCContentSharingPickerConfiguration::new().expect("create picker configuration");
SCContentSharingPicker::show(&config, |outcome| {
if let SCPickerOutcome::Picked(result) = outcome {
let (width, height) = result.pixel_size();
let filter = result.filter();
// ... create stream
}
});§Example (async)
use screencapturekit::async_api::AsyncSCContentSharingPicker;
use screencapturekit::content_sharing_picker::*;
async fn example() {
let config = SCContentSharingPickerConfiguration::new().expect("create picker configuration");
if let SCPickerOutcome::Picked(result) = AsyncSCContentSharingPicker::show(&config).await {
let (width, height) = result.pixel_size();
let filter = result.filter();
// ... create stream
}
}Implementations§
Source§impl SCContentSharingPicker
impl SCContentSharingPicker
Sourcepub fn is_available() -> bool
pub fn is_available() -> bool
Whether content-sharing picker APIs are available on this system.
Sourcepub fn show<F>(config: &SCContentSharingPickerConfiguration, callback: F)
pub fn show<F>(config: &SCContentSharingPickerConfiguration, callback: F)
Show the picker UI with a callback for the result
This is non-blocking - the callback is invoked when the user makes a selection or cancels the picker.
§Example
use screencapturekit::content_sharing_picker::*;
let config = SCContentSharingPickerConfiguration::new().expect("create picker configuration");
SCContentSharingPicker::show(&config, |outcome| {
match outcome {
SCPickerOutcome::Picked(result) => {
let (width, height) = result.pixel_size();
let filter = result.filter();
println!("Selected {}x{}", width, height);
}
SCPickerOutcome::Cancelled => println!("Cancelled"),
SCPickerOutcome::Error(e) => eprintln!("Error: {}", e),
}
});Sourcepub fn show_for_stream<F>(
config: &SCContentSharingPickerConfiguration,
stream: &SCStream,
callback: F,
)
pub fn show_for_stream<F>( config: &SCContentSharingPickerConfiguration, stream: &SCStream, callback: F, )
Show the picker UI for an existing stream (to change source while capturing)
Use this when you have an active SCStream and want to let the user
select a new content source. The callback receives the new filter
which can be used with stream.update_content_filter().
§Example
use screencapturekit::content_sharing_picker::*;
use screencapturekit::stream::SCStream;
use screencapturekit::stream::configuration::SCStreamConfiguration;
use screencapturekit::stream::content_filter::SCContentFilter;
use screencapturekit::shareable_content::SCShareableContent;
fn example() -> Option<()> {
let content = SCShareableContent::get().ok()?;
let displays = content.displays();
let display = displays.first()?;
let filter = SCContentFilter::create().with_display(display).with_excluding_windows(&[]).build().ok()?;
let stream_config = SCStreamConfiguration::new();
let stream = SCStream::new(&filter, &stream_config).ok()?;
// When stream is active and user wants to change source
let config = SCContentSharingPickerConfiguration::new().ok()?;
SCContentSharingPicker::show_for_stream(&config, &stream, |outcome| {
if let SCPickerOutcome::Picked(result) = outcome {
// Use result.filter() with stream.update_content_filter()
let _ = result.filter();
}
});
Some(())
}Sourcepub fn show_filter<F>(config: &SCContentSharingPickerConfiguration, callback: F)
pub fn show_filter<F>(config: &SCContentSharingPickerConfiguration, callback: F)
Show the picker UI with a callback that receives just the filter
This is the simple API - use when you just need the filter without metadata.
§Example
use screencapturekit::content_sharing_picker::*;
let config = SCContentSharingPickerConfiguration::new().expect("create picker configuration");
SCContentSharingPicker::show_filter(&config, |outcome| {
if let SCPickerFilterOutcome::Filter(filter) = outcome {
// Use filter with SCStream
}
});Sourcepub fn show_using_style<F>(
config: &SCContentSharingPickerConfiguration,
style: SCShareableContentStyle,
callback: F,
)
pub fn show_using_style<F>( config: &SCContentSharingPickerConfiguration, style: SCShareableContentStyle, callback: F, )
Show the picker UI with a specific content style
Presents the picker pre-filtered to a specific content type.
§Arguments
config- The picker configurationstyle- The content style to show (Window, Display, Application)callback- Called with the picker result
Sourcepub fn show_for_stream_using_style<F>(
config: &SCContentSharingPickerConfiguration,
stream: &SCStream,
style: SCShareableContentStyle,
callback: F,
)
pub fn show_for_stream_using_style<F>( config: &SCContentSharingPickerConfiguration, stream: &SCStream, style: SCShareableContentStyle, callback: F, )
Show the picker for an existing stream with a specific content style
§Arguments
config- The picker configurationstream- The stream to updatestyle- The content style to show (Window, Display, Application)callback- Called with the picker result
Sourcepub fn set_maximum_stream_count(
count: usize,
) -> Result<(), SCPickerConfigurationError>
pub fn set_maximum_stream_count( count: usize, ) -> Result<(), SCPickerConfigurationError>
Set the maximum number of streams that can be created from the picker
Pass 0 to allow unlimited streams.
Sourcepub fn maximum_stream_count() -> usize
pub fn maximum_stream_count() -> usize
Get the maximum number of streams allowed
Returns 0 if unlimited streams are allowed.
Sourcepub fn is_active() -> bool
pub fn is_active() -> bool
Returns whether the shared content-sharing picker is currently marked active.
Apple requires picker.isActive = true before its UI can appear.
The various show*() trampolines on this type set it implicitly
before presenting, but this getter is useful for callers that
want to:
- avoid double-presenting (skip a second
show()while the first picker session is still up), - render UI affordances based on whether the picker is currently visible to the user.
Sourcepub fn set_active(active: bool) -> Result<(), SCPickerConfigurationError>
pub fn set_active(active: bool) -> Result<(), SCPickerConfigurationError>
Mark the shared content-sharing picker active or inactive.
Setting this to false hides the picker UI between sessions
(the recommended hygiene step after a long-running app finishes
using the picker — leaving it active leaves the system-level
Control Center entry in a “ready to share” state).
Setting to true is required before present*() can surface
the picker; the show*() trampolines do this for you. Set it
manually only if you want to opt into the picker UI without
immediately presenting it.
Sourcepub fn deactivate()
pub fn deactivate()
Deactivate the picker and undo any activation-policy promotion the
bridge performed on behalf of a non-UI (.prohibited) host process.
Presenting SCContentSharingPicker requires the process to be a
regular, Dock-visible app. Pure-Rust hosts usually are not, so the
bridge temporarily promotes them; the promotion is reference counted
and unwound automatically when each one-shot show*() resolves. Call
this after you are done with a long-lived observer session to drop
the promotion immediately and clear the Control Center “ready to
share” indicator.
Registered observers are not removed — drop their
SCPickerSubscription for that.
Sourcepub fn default_configuration() -> Result<SCContentSharingPickerConfiguration, SCError>
pub fn default_configuration() -> Result<SCContentSharingPickerConfiguration, SCError>
Read the picker’s process-wide default configuration.
Equivalent to Apple’s SCContentSharingPicker.shared.defaultConfiguration.
This is the same value returned by
SCContentSharingPickerConfiguration::default_from_system.
§Errors
Returns SCError::FeatureNotAvailable when run on macOS older than
14.0.
Sourcepub fn set_default_configuration(
config: &SCContentSharingPickerConfiguration,
) -> Result<(), SCPickerConfigurationError>
pub fn set_default_configuration( config: &SCContentSharingPickerConfiguration, ) -> Result<(), SCPickerConfigurationError>
Assign the picker’s process-wide default configuration.
Apple’s SCContentSharingPicker.defaultConfiguration is read-write;
previously this crate could only set it as a side effect of calling a
show*() helper. Setting it explicitly is what you want when driving
the picker with a persistent observer plus Self::present.
§Examples
use screencapturekit::content_sharing_picker::*;
let mut config = SCContentSharingPickerConfiguration::new().expect("create picker configuration");
config.set_allows_changing_selected_content(true);
SCContentSharingPicker::set_default_configuration(&config)
.expect("call from the process main thread");The assignment is complete when this method returns, so an immediate
call to Self::default_configuration observes the new value.
§Errors
Returns SCPickerConfigurationError::Unavailable when the API is
unavailable, or SCPickerConfigurationError::MainThreadRequired
when called from any other thread. Failed calls do not enqueue a later
mutation.
Sourcepub fn set_configuration_for_stream(
config: Option<&SCContentSharingPickerConfiguration>,
stream: &SCStream,
) -> Result<(), SCPickerConfigurationError>
pub fn set_configuration_for_stream( config: Option<&SCContentSharingPickerConfiguration>, stream: &SCStream, ) -> Result<(), SCPickerConfigurationError>
Assign a picker configuration scoped to a single stream, mirroring
Apple’s setConfiguration(_:for:).
Pass None to clear the stream-specific configuration and fall back to
the process-wide default.
The assignment is complete when this method returns.
§Errors
Returns SCPickerConfigurationError::Unavailable when the API is
unavailable, or SCPickerConfigurationError::MainThreadRequired
when called from any other thread. Failed calls do not enqueue a later
mutation.
Sourcepub fn add_observer<F>(
handler: F,
) -> Result<SCPickerSubscription, SCPickerConfigurationError>
pub fn add_observer<F>( handler: F, ) -> Result<SCPickerSubscription, SCPickerConfigurationError>
Register a repeating observer that receives every picker event for as long as the returned subscription is alive.
This is the API to use with
SCContentSharingPickerConfiguration::set_allows_changing_selected_content:
Apple re-invokes contentSharingPicker(_:didUpdateWith:for:) each time
the user re-picks during an active share, and the one-shot
Self::show family deliberately latches after the first event.
The subscription unregisters on drop, so bind it to a variable that
lives as long as you want events (use SCPickerSubscription::detach
to keep it for the remainder of the process).
Pair this with Self::present / Self::present_for_stream to
surface the UI.
Apple marks SCContentSharingPicker as @MainActor. Call this on the
process main thread, or while an AppKit main run loop is active so the
bridge can synchronously hop to it.
§Errors
Returns SCPickerConfigurationError::Unavailable below macOS 14.0,
and SCPickerConfigurationError::MainThreadRequired when called off
the main thread without an active main run loop.
§Examples
use screencapturekit::content_sharing_picker::*;
let mut config = SCContentSharingPickerConfiguration::new().expect("create picker configuration");
config.set_allows_changing_selected_content(true);
SCContentSharingPicker::set_default_configuration(&config)
.expect("call from the process main thread");
let subscription = SCContentSharingPicker::add_observer(|event| match event {
SCPickerEvent::Updated { result, stream } => {
// Fires again every time the user changes their selection.
let _filter = result.filter();
let _existing_stream = stream;
}
SCPickerEvent::Cancelled { .. } => println!("cancelled"),
SCPickerEvent::Failed(err) => eprintln!("picker failed: {err}"),
}).expect("register picker observer");
SCContentSharingPicker::present().expect("present picker");
// ... keep `subscription` alive for as long as you want updates ...
drop(subscription);Sourcepub fn remove_all_observers() -> usize
pub fn remove_all_observers() -> usize
Remove every repeating observer registered through
Self::add_observer, regardless of which subscriptions are still
alive. Returns how many were removed.
Dropping the corresponding SCPickerSubscription afterwards is
harmless — removal is idempotent.
Sourcepub fn present() -> Result<(), SCPickerConfigurationError>
pub fn present() -> Result<(), SCPickerConfigurationError>
Present the picker without a content-style hint.
Use with Self::add_observer; the one-shot Self::show family
presents for you.
Sourcepub fn present_using_style(
style: SCShareableContentStyle,
) -> Result<(), SCPickerConfigurationError>
pub fn present_using_style( style: SCShareableContentStyle, ) -> Result<(), SCPickerConfigurationError>
Present the picker preselecting a content style.
Sourcepub fn present_for_stream(
stream: &SCStream,
) -> Result<(), SCPickerConfigurationError>
pub fn present_for_stream( stream: &SCStream, ) -> Result<(), SCPickerConfigurationError>
Present the picker targeting an existing stream, so the user can swap the shared source mid-capture.
Sourcepub fn present_for_stream_using_style(
stream: &SCStream,
style: SCShareableContentStyle,
) -> Result<(), SCPickerConfigurationError>
pub fn present_for_stream_using_style( stream: &SCStream, style: SCShareableContentStyle, ) -> Result<(), SCPickerConfigurationError>
Present the picker targeting an existing stream, preselecting a style.