Skip to main content

DesktopExtensions

Trait DesktopExtensions 

Source
pub trait DesktopExtensions {
    // Provided methods
    fn on_event_loop_builder(&mut self, builder: &mut DesktopEventLoopBuilder) { ... }
    fn on_window_attributes(
        &mut self,
        attributes: WindowAttributes,
    ) -> WindowAttributes { ... }
    fn on_window_created(&mut self, window: &Arc<Window>) { ... }
    fn pump(&mut self) { ... }
    fn on_theme_brightness_changed(&mut self, brightness: Brightness) { ... }
    fn on_platform_view_commands(
        &mut self,
        window: &Arc<Window>,
        scale: f64,
        commands: &[ViewCommand],
    ) { ... }
    fn on_platform_views_suspended(&mut self) { ... }
    fn on_close_requested(&mut self) -> CloseAction { ... }
}
Expand description

The hooks a per-OS desktop shell implements to add native behavior to this shared winit core.

Every method has a no-op default, so an implementation writes only the hooks it uses; NoExtensions implements none at all. The eight hooks, in the order a running app meets them:

  1. on_event_loop_builder — before the loop is built.
  2. on_window_attributes — before the window is created.
  3. on_window_created — after it is created, before it is shown.
  4. pump — once per frame, at the top.
  5. on_theme_brightness_changed — whenever the resolved theme brightness changes.
  6. on_platform_view_commands — once per frame, after the frame is submitted, when a hosted native view needs creating, placing or tearing down.
  7. on_platform_views_suspended — when the window or its surface goes away and every hosted view must go with it.
  8. on_close_requested — on a close request.

Provided Methods§

Source

fn on_event_loop_builder(&mut self, builder: &mut DesktopEventLoopBuilder)

Called with the winit event-loop builder, before build().

The one hook that runs before anything else exists — no runtime, no window, no frame. Its purpose is the platform-specific builder extensions winit only accepts here, notably EventLoopBuilderExtWindows::with_msg_hook (the message hook a Windows shell needs so TranslateAcceleratorW can turn a menu accelerator into a menu event before winit consumes the key).

Source

fn on_window_attributes( &mut self, attributes: WindowAttributes, ) -> WindowAttributes

Called with the window attributes the core assembled from DesktopConfig, returning the attributes to actually create the window with.

Runs after the core’s own defaults (title, initial size, and the visible(false) the accessibility adapter’s creation contract requires), so an extension can override any of them — a Linux shell attaching with_name (Wayland app_id/X11 WM_CLASS) or a window icon does it here, since winit accepts neither after creation.

Leaving visible alone matters: the adapter must be constructed before the window is ever shown, and this core makes it visible itself once that is done.

Source

fn on_window_created(&mut self, window: &Arc<Window>)

Called once, immediately after the window is created and its accessibility adapter constructed, but before the window is shown.

This is where a native menu is attached to the live window handle (muda’s init_for_nsapp/init_for_hwnd) and where a platform identity call that needs the window (a Windows AppUserModelID, a taskbar icon) belongs.

It is also the only hook that receives the window: clone the Arc if a later hook needs it (see the module docs).

Source

fn pump(&mut self)

Called once per frame, at the top of the redraw pass — before the theme and font polls, and before the rebuild.

This is the per-OS half of the signal-poll seam idiom: a shell hands over at most one queued activation per frame through frust_reactive::push_menu_event (the seam is a single-slot signal, so a batch pushed in one pass would coalesce to its last entry) and requests another frame while more remain queued. The position guarantees the activation delivered on this frame is visible to this frame’s rebuild rather than waiting for the next one.

Source

fn on_theme_brightness_changed(&mut self, brightness: Brightness)

Called whenever the shell’s resolved theme brightness actually changes — its first resolution in resumed, a platform appearance change (WindowEvent::ThemeChanged), and an app-forced override arriving or clearing through the per-frame set_app_theme/clear_app_theme poll.

“Actually changes” is enforced by the core, which tracks the last value it reported: a re-push at unchanged brightness (an override swapping one dark theme for another) fires nothing, and the hook never fires per-frame.

The motivating consumer is the Windows titlebar: winit themes it from the system preference on its own, so only an app-forced theme needs the shell to call Window::set_theme — which is why the hook must fire on the override path and not merely on the platform event.

Source

fn on_platform_view_commands( &mut self, window: &Arc<Window>, scale: f64, commands: &[ViewCommand], )

Called on the UI thread right after a frame is submitted, with the platform-view differ’s pending command batch in generation order — the per-OS half of the desktop platform-view host (this crate owns the OS-neutral half; see crate::platform_view).

A host creates, places, shows/hides, re-parameterizes and disposes its native sibling views from this batch, parented into window. Contract:

  • Rects and clips are logical points (winit logical units, absolute window coordinates) — deliberately not converted to physical px the way the mobile shells convert at their FFI boundary, because AppKit (the first consumer) places NSViews in logical points. scale is the window’s current scale_factor(), for a host that does need physical px — it scales at its own boundary.
  • Apply the batch idempotently, per ViewCommand semantics: the whole not-yet-applied backlog is re-served if a batch is ever missed, so an already-applied prefix may arrive twice, an Update for an unknown slot must be ignored rather than treated as a create, and a Dispose for a slot already gone must be a no-op.
  • Do not block. This runs between submitting a frame and the next event-loop turn on the thread that owns the window; a blocking call here stalls the frame loop directly.

Called only when there is something to apply — an unchanged frame (the common case: nothing hosted, or a static hosted view) never reaches the hook at all.

Source

fn on_platform_views_suspended(&mut self)

Called when the window is destroyed or its surface lost: remove every hosted native view.

Not a hide — the view hierarchy this core was placing views into is going away, so a host that merely hides them leaks them. The commands queued at this moment are discarded rather than delivered (they describe views that no longer exist); on the way back in, the next on_platform_view_commands batch is a full Create + Update replay of every live slot, so a host rebuilds from that batch alone and needs to retain nothing across the gap.

Source

fn on_close_requested(&mut self) -> CloseAction

Called on WindowEvent::CloseRequested, deciding whether the loop exits.

The default is CloseAction::Exit — this shell’s historical unconditional behavior, and therefore what the dev preview still does. A macOS shell returns CloseAction::KeepRunning after hiding its retained window when DesktopConfig::quit_on_last_window_closed is false, and lets the platform Quit item exit later; the pipeline-cache persistence path runs on that real exit either way, since it hangs off the frame executor’s drop when run_app returns rather than off this event.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§