///|
/// Platform projection owned by the logical window lifecycle. The closures
/// carry native effects; frame, image, input, and service state remain in
/// their dedicated owners.
pub(all) struct WindowSurfaceActions {
focus : () -> Unit
request_resize : (@core.SurfaceMetrics) -> @core.SurfaceMetrics
sync_observed_resize : (@core.SurfaceMetrics) -> @core.SurfaceMetrics
set_minimized : (Bool) -> Unit
set_visible : (Bool) -> Unit
request_redraw : () -> Unit
request_ime_update : (@window_input.TextInputSessionAction) -> Unit
set_drag_region : (@core.Rect?) -> Unit
drop : () -> Unit
native_view_handle : () -> UInt64?
dispose_platform_views : () -> Unit
}
///|
pub fn WindowSurfaceActions::new(
focus~ : () -> Unit,
request_resize~ : (@core.SurfaceMetrics) -> @core.SurfaceMetrics,
sync_observed_resize~ : (@core.SurfaceMetrics) -> @core.SurfaceMetrics,
set_minimized~ : (Bool) -> Unit,
set_visible~ : (Bool) -> Unit,
request_redraw~ : () -> Unit,
request_ime_update~ : (@window_input.TextInputSessionAction) -> Unit,
set_drag_region? : (@core.Rect?) -> Unit = _ => (),
drop~ : () -> Unit,
native_view_handle~ : () -> UInt64?,
dispose_platform_views~ : () -> Unit,
) -> WindowSurfaceActions {
{
focus,
request_resize,
sync_observed_resize,
set_minimized,
set_visible,
request_redraw,
request_ime_update,
set_drag_region,
drop,
native_view_handle,
dispose_platform_views,
}
}
///|
priv struct WindowSurfaceEntry {
id : @backend_host.WindowId
actions : WindowSurfaceActions
}
///|
/// Logical host-window owner. It intentionally contains no renderer, image,
/// input-session, or service-bridge state.
pub struct WindowLifecycle {
priv requests : @backend_host.WindowRequests
priv scene_resolver : WindowSceneResolver
priv windows : WindowRegistry
priv runtime_slots : WindowRuntimeSlots
priv platform_windows : PlatformWindowMap
priv ledger : WindowLifecycleCore
priv mut surface_generation : Int
priv mut exit_intent : Int?
priv mut surfaces : Array[WindowSurfaceEntry]
}
///|
pub fn WindowLifecycle::new(
requests~ : @backend_host.WindowRequests,
scene_resolver~ : WindowSceneResolver,
) -> WindowLifecycle {
{
requests,
scene_resolver,
windows: WindowRegistry::new(),
runtime_slots: WindowRuntimeSlots::new(),
platform_windows: PlatformWindowMap::new(),
ledger: WindowLifecycleCore::new(),
surface_generation: 0,
exit_intent: None,
surfaces: [],
}
}
///|
pub fn WindowLifecycle::window_registry(
self : WindowLifecycle,
) -> WindowRegistry {
self.windows
}
///|
pub fn WindowLifecycle::runtime_slots(
self : WindowLifecycle,
) -> WindowRuntimeSlots {
self.runtime_slots
}
///|
pub fn WindowLifecycle::runtime_slots_empty(self : WindowLifecycle) -> Bool {
self.runtime_slots.is_empty()
}
///|
pub fn WindowLifecycle::runtime_slot_lookup(
self : WindowLifecycle,
id : @backend_host.WindowId,
) -> WindowRuntimeSlot? {
self.runtime_slots.lookup(id)
}
///|
pub fn WindowLifecycle::active_runtime_slot(
self : WindowLifecycle,
) -> WindowRuntimeSlot? {
match self.runtime_slots.focused_slot() {
Some(slot) => Some(slot)
None => self.runtime_slots.primary_slot()
}
}
///|
pub fn WindowLifecycle::bind_platform_window(
self : WindowLifecycle,
platform_id~ : @window_core.WindowId,
window_id~ : @backend_host.WindowId,
) -> Bool {
self.platform_windows.bind(platform_id~, host_id=window_id)
}
///|
pub fn WindowLifecycle::lookup_window(
self : WindowLifecycle,
platform_id : @window_core.WindowId,
) -> @backend_host.WindowId? {
self.platform_windows.lookup_host(platform_id)
}
///|
pub fn WindowLifecycle::unbind_platform_window(
self : WindowLifecycle,
window_id : @backend_host.WindowId,
) -> @window_core.WindowId? {
self.platform_windows.remove_host(window_id)
}
///|
pub fn WindowLifecycle::attach_surface(
self : WindowLifecycle,
id : @backend_host.WindowId,
actions : WindowSurfaceActions,
) -> Bool {
if self.surface_actions(id) is Some(_) {
return false
}
self.surfaces.push({ id, actions, })
self.surface_generation = self.surface_generation + 1
true
}
///|
pub fn WindowLifecycle::surface_actions(
self : WindowLifecycle,
id : @backend_host.WindowId,
) -> WindowSurfaceActions? {
for surface in self.surfaces {
if surface.id == id {
return Some(surface.actions)
}
}
None
}
///|
pub fn WindowLifecycle::detach_surface(
self : WindowLifecycle,
id : @backend_host.WindowId,
) -> WindowSurfaceActions? {
let mut removed = None
let kept = []
for surface in self.surfaces {
if surface.id == id {
removed = Some(surface.actions)
} else {
kept.push(surface)
}
}
self.surfaces = kept
if removed is Some(_) {
self.surface_generation = self.surface_generation + 1
}
removed
}
///|
pub fn WindowLifecycle::surface_generation(self : WindowLifecycle) -> Int {
self.surface_generation
}
///|
pub fn WindowLifecycle::request_exit(
self : WindowLifecycle,
code : Int,
) -> Unit {
self.exit_intent = Some(code)
}
///|
pub fn WindowLifecycle::exit_intent(self : WindowLifecycle) -> Int? {
self.exit_intent
}
///|
pub fn WindowLifecycle::open_resolution(
self : WindowLifecycle,
request : @backend_host.WindowOpenRequest,
) -> WindowOpenResolution {
resolve_open_request(self.windows, request, self.scene_resolver)
}
///|
pub fn WindowLifecycle::drain_window_requests(
self : WindowLifecycle,
apply : (@backend_host.WindowRequest) -> @backend_host.WindowRequestResult,
) -> Unit {
ignore(self.requests.drain_with_handler(apply))
}
///|
pub fn WindowLifecycle::register_runtime_slot(
self : WindowLifecycle,
slot : WindowRuntimeSlot,
) -> Bool {
if !self.ledger.register(slot.id) {
return false
}
if self.runtime_slots.insert(slot) {
true
} else {
ignore(self.ledger.rollback(slot.id))
false
}
}
///|
pub fn WindowLifecycle::register_primary_runtime_slot(
self : WindowLifecycle,
id : @backend_host.WindowId,
driver : @runtime.HostRuntimeDriver,
) -> Unit {
match self.windows.lookup(id) {
Some(record) =>
ignore(
self.register_runtime_slot(
WindowRuntimeSlot::from_driver(record~, driver~),
),
)
None => ()
}
}
///|
pub fn WindowLifecycle::sync_runtime_slot(
self : WindowLifecycle,
id : @backend_host.WindowId,
) -> Unit {
ignore(self.runtime_slots.sync_from_registry(self.windows, id))
}
///|
pub fn WindowLifecycle::sync_runtime_slots(self : WindowLifecycle) -> Unit {
ignore(self.runtime_slots.sync_open_from_registry(self.windows))
}
///|
pub fn WindowLifecycle::apply_request_state(
self : WindowLifecycle,
request : @backend_host.WindowRequest,
) -> @backend_host.WindowRequestResult {
self.runtime_slots.apply_request(self.windows, request)
}
///|
pub fn WindowLifecycle::apply_host_event(
self : WindowLifecycle,
id : @backend_host.WindowId,
event : @backend_host.Event,
) -> Bool {
self.runtime_slots.apply_host_event(self.windows, id, event)
}
///|
pub fn WindowLifecycle::begin_close(
self : WindowLifecycle,
id : @backend_host.WindowId,
) -> Bool {
self.ledger.begin_close(id)
}
///|
pub fn WindowLifecycle::finish_close(
self : WindowLifecycle,
id : @backend_host.WindowId,
) -> Unit {
ignore(self.windows.close(id))
self.sync_runtime_slot(id)
ignore(self.runtime_slots.remove(id))
ignore(self.unbind_platform_window(id))
ignore(self.detach_surface(id))
ignore(self.windows.remove_closed())
self.sync_runtime_slots()
ignore(self.ledger.finish_close(id))
}
///|
pub fn WindowLifecycle::rollback_window_record(
self : WindowLifecycle,
id : @backend_host.WindowId,
) -> Unit {
ignore(self.ledger.rollback(id))
ignore(self.unbind_platform_window(id))
ignore(self.detach_surface(id))
ignore(self.windows.close(id))
ignore(self.windows.remove_closed())
self.sync_runtime_slots()
}