///|
/// Shared transformer for a subset of `@window_core.WindowEvent` variants
/// that have fully cross-platform semantics. Events carrying platform-
/// specific payloads (Pointer, Keyboard, Ime, Drag, Modifiers) are
/// dispatched through `@backend_host.window_event_to_host_event` directly by
/// each platform's app_handler and are NOT transformed here.
///
/// This keeps the shared adapter focused on truly shared logic and avoids
/// losing semantic information in the translation.
///|
/// Result of transforming a cross-platform `WindowEvent`.
pub(all) enum TransformedWindowEvent {
/// Forward a `Event` to the runtime driver.
DispatchHostEvent(@backend_host.Event)
/// Request a full window redraw (from `RedrawRequested`).
WindowRedrawRequired
/// Window should be closed and its resources released.
CloseRequested
/// No action needed or event was platform-specific.
PlatformSpecific
}
///|
/// Neutral surface lifecycle state shared by window-hosted and desktop
/// adapters. Platform packages keep the native surface handles and own their
/// attach/detach callbacks; the bridge owns only the logical lifecycle state.
pub(all) enum PlatformSurfaceLifecycle {
Detached
Attached(@core.SurfaceMetrics)
} derive(Eq, Debug)
///|
pub extend PlatformSurfaceLifecycle with Debug::{to_repr}
///|
pub extend PlatformSurfaceLifecycle with Eq::{not_equal, equal}
///|
pub fn PlatformSurfaceLifecycle::attach(
metrics : @core.SurfaceMetrics,
) -> PlatformSurfaceLifecycle {
Attached(metrics)
}
///|
pub fn PlatformSurfaceLifecycle::detach(
_self : PlatformSurfaceLifecycle,
) -> PlatformSurfaceLifecycle {
Detached
}
///|
pub fn PlatformSurfaceLifecycle::metrics(
self : PlatformSurfaceLifecycle,
) -> @core.SurfaceMetrics? {
match self {
Attached(metrics) => Some(metrics)
Detached => None
}
}
///|
/// Transform a cross-platform `WindowEvent` that carries no platform-
/// specific payload. Events that require native decode (pointer, keyboard,
/// IME, drag, modifiers) return `PlatformSpecific` — the caller's
/// platform-local handler should process them directly via
/// `@backend_host.window_event_to_host_event`.
///
/// The event payload is authoritative for resize and scale changes. The
/// optional arguments remain for adapters that also track an observed native
/// surface, but are deliberately ignored for those variants so stale external
/// state cannot overwrite the callback payload.
pub fn transform_cross_platform_event(
event : @window_core.WindowEvent,
scale_factor~ : Double,
surface_size? : @dpi.PhysicalSize? = None,
) -> TransformedWindowEvent {
ignore(surface_size)
match event {
CloseRequested => CloseRequested
SurfaceResized(size) => make_resized_event(scale_factor, Some(size))
ScaleFactorChanged(scale, writer) =>
make_resized_event(scale, Some(writer.surface_size()))
Focused(focused) =>
DispatchHostEvent(Focus(@backend_host.HostFocusEvent::new(focused~)))
RedrawRequested => WindowRedrawRequired
// Platform-specific events: the caller must dispatch via
// `@backend_host.window_event_to_host_event` for proper handling.
PointerMoved(_)
| PointerButton(_)
| DragEntered(_)
| DragMoved(_)
| DragDropped(_)
| DragLeft(_)
| KeyboardInput(_)
| Ime(_)
| ModifiersChanged(_) => PlatformSpecific
_ => PlatformSpecific
}
}
///|
fn make_resized_event(
scale_factor : Double,
surface_size : @dpi.PhysicalSize?,
) -> TransformedWindowEvent {
match surface_size {
Some(size) =>
DispatchHostEvent(
Resized(surface_metrics_from_physical(size, scale_factor~)),
)
None => PlatformSpecific
}
}
///|
/// Compute `@core.SurfaceMetrics` from a physical size and scale factor.
/// Convenience wrapper for callers that need the metrics outside of
/// the event transformer.
pub fn make_surface_metrics(
size : @dpi.PhysicalSize,
scale_factor~ : Double,
) -> @core.SurfaceMetrics {
surface_metrics_from_physical(size, scale_factor~)
}
///|
/// Cross-platform handler for pointer position normalization.
/// Every platform normalizes native pointer positions to logical
/// coordinates for the runtime.
pub fn normalize_pointer_position(
position : @dpi.PhysicalPositionF64,
scale_factor~ : Double,
) -> @core.Point {
physical_position_to_core(position, scale_factor~)
}