Skip to content

Add Send + Sync for SubclassingAdapter, remove visibility panic#1

Open
jshin-tacticalid wants to merge 3 commits into
wash2:iced-0.14from
jshin-tacticalid:tip-send-sync-fixes
Open

Add Send + Sync for SubclassingAdapter, remove visibility panic#1
jshin-tacticalid wants to merge 3 commits into
wash2:iced-0.14from
jshin-tacticalid:tip-send-sync-fixes

Conversation

@jshin-tacticalid
Copy link
Copy Markdown

Summary

When using accesskit with iced's event loop, two issues prevent compilation and correct initialization:

  1. SubclassingAdapter is not Send/Sync — iced's Proxy<T> wraps the adapter in a channel, which requires Send + Sync. The adapter uses RefCell internally, but it is always created and accessed on the UI thread (main thread on macOS, window thread on Windows). The channel bounds are structural, not behavioral.

  2. Visibility panic on WindowsSubclassingAdapter::new() and Adapter::with_direct_handlers() panic if the window is already visible. Some frameworks (iced, and likely others) show the window before processing adapter initialization. Window subclassing works fine on visible windows — the panic is overly strict.

Changes

  • accesskit_macos/src/subclass.rs: unsafe impl Send + Sync for SubclassingAdapter
  • accesskit_windows/src/subclass.rs: unsafe impl Send + Sync for SubclassingAdapter, remove IsWindowVisible check
  • accesskit_winit/src/lib.rs: Remove visibility panic, update doc from "# Panics" to "# Note"
  • accesskit_winit/src/platform_impl/windows.rs: Accept &dyn Window for consistency

Safety

The Send + Sync impls are safe because:

  • macOS: NSAccessibility callbacks only fire on the main thread
  • Windows: WM_GETOBJECT and focus callbacks only fire on the window's thread
  • The adapters are never actually accessed from multiple threads — the bounds are required by channel infrastructure, not by cross-thread usage

iced's Proxy<T> requires Send + Sync for its Notifier trait because it
wraps the adapter in a channel. The SubclassingAdapter uses RefCell
internally, which is not Send/Sync.

This is safe because the SubclassingAdapter is always created and accessed
on the main thread. The Send + Sync bounds come from iced's channel
infrastructure, not actual cross-thread usage. Accessibility callbacks
(NSAccessibility) only fire on the window's thread.
…ity panic

Two changes:

1. Add unsafe Send + Sync implementations for SubclassingAdapter, matching
   the macOS change. The adapter is always accessed on the UI thread;
   WM_GETOBJECT and focus callbacks only fire on the window's thread.

2. Remove the IsWindowVisible panic in SubclassingAdapter::new(). Some
   frameworks (notably iced) process adapter initialization after the window
   is already shown — this is normal lifecycle behavior, not an error.
   Window subclassing works fine on visible windows.
1. Remove the panic when the window is already visible at adapter creation
   time. Update doc comment from "# Panics" to "# Note" explaining that
   pre-visibility creation is preferred but not required.

2. Change Windows platform adapter to accept &dyn Window instead of &Window
   for consistency with the trait-based API.
@jshin-tacticalid jshin-tacticalid marked this pull request as ready for review March 31, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant