diff --git a/src/event.rs b/src/event.rs index 81ed975ac..ea17b170f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -169,6 +169,38 @@ pub enum Event<'a, T: 'static> { /// This lets you determine why the scene was requested. options: objc2::rc::Retained, }, + + /// Emitted when the application has been started. + /// + /// ## Platform-specific + /// + /// - **OHOS**: Triggered by `onAbilityStart` lifecycle callback. + /// - **Other**: Unsupported. + #[cfg(target_env = "ohos")] + Started, + + /// Emitted when the system requests the application to save its state. + /// + /// ## Platform-specific + /// + /// - **OHOS**: Triggered by `onAbilitySaveState` lifecycle callback. + /// - **Other**: Unsupported. + #[cfg(target_env = "ohos")] + SaveStateRequested, + + /// Emitted when the application's content rect has changed (e.g. keyboard shown/hidden). + /// + /// ## Platform-specific + /// + /// - **OHOS**: Triggered by `window.on("contentRectChange")` callback. + /// - **Other**: Unsupported. + #[cfg(target_env = "ohos")] + ContentRectChanged { + /// The new content rectangle (left, top, width, height). + rect: (i32, i32, i32, i32), + /// Reason for the change. + reason: u32, + }, } impl Clone for Event<'static, T> { @@ -202,6 +234,15 @@ impl Clone for Event<'static, T> { scene: scene.clone(), options: options.clone(), }, + #[cfg(target_env = "ohos")] + Started => Started, + #[cfg(target_env = "ohos")] + SaveStateRequested => SaveStateRequested, + #[cfg(target_env = "ohos")] + ContentRectChanged { rect, reason } => ContentRectChanged { + rect: *rect, + reason: *reason, + }, } } } @@ -228,6 +269,12 @@ impl<'a, T> Event<'a, T> { }), #[cfg(target_os = "ios")] SceneRequested { scene, options } => Ok(SceneRequested { scene, options }), + #[cfg(target_env = "ohos")] + Started => Ok(Started), + #[cfg(target_env = "ohos")] + SaveStateRequested => Ok(SaveStateRequested), + #[cfg(target_env = "ohos")] + ContentRectChanged { rect, reason } => Ok(ContentRectChanged { rect, reason }), } } @@ -256,6 +303,12 @@ impl<'a, T> Event<'a, T> { }), #[cfg(target_os = "ios")] SceneRequested { scene, options } => Some(SceneRequested { scene, options }), + #[cfg(target_env = "ohos")] + Started => Some(Started), + #[cfg(target_env = "ohos")] + SaveStateRequested => Some(SaveStateRequested), + #[cfg(target_env = "ohos")] + ContentRectChanged { rect, reason } => Some(ContentRectChanged { rect, reason }), } } } diff --git a/src/platform_impl/ohos/mod.rs b/src/platform_impl/ohos/mod.rs index 1e953320e..79ba2f43a 100644 --- a/src/platform_impl/ohos/mod.rs +++ b/src/platform_impl/ohos/mod.rs @@ -510,13 +510,28 @@ impl EventLoop { // Propagate as Resized so tauri's resize handler fires and calls // webview.set_bounds() with the new window dimensions. let size = PhysicalSize::new(content_rect.rect.width as _, content_rect.rect.height as _); - let event = event::Event::WindowEvent { + let resized_event = event::Event::WindowEvent { window_id: window::WindowId(WindowId), event: event::WindowEvent::Resized(size), }; if let Some(ref mut h) = *self.event_loop.borrow_mut() { - h(event); + h(resized_event); + + // Also emit ContentRectChanged for lifecycle-aware applications + let reason = match content_rect.reason { + openharmony_ability::RectChangeReason::Undefined => 0, + openharmony_ability::RectChangeReason::Maximize => 1, + openharmony_ability::RectChangeReason::Recover => 2, + openharmony_ability::RectChangeReason::Move => 3, + openharmony_ability::RectChangeReason::Drag => 4, + openharmony_ability::RectChangeReason::DragStart => 5, + openharmony_ability::RectChangeReason::DragEnd => 6, + }; + h(event::Event::ContentRectChanged { + rect: (content_rect.rect.left, content_rect.rect.top, content_rect.rect.width, content_rect.rect.height), + reason, + }); } } MainEvent::GainedFocus => { @@ -556,23 +571,39 @@ impl EventLoop { } } MainEvent::Start => { - // XXX: how to forward this state to applications? - warn!("TODO: forward onStart notification to application"); + if let Some(ref mut h) = *self.event_loop.borrow_mut() { + h(event::Event::Started); + } } MainEvent::Resume { .. } => { + // NOTE: The SaveLoader handle for state restoration is intentionally + // discarded. State I/O is not yet wired through to applications. if let Some(ref mut h) = *self.event_loop.borrow_mut() { h(event::Event::Resumed); } } MainEvent::SaveState { .. } => { - // XXX: how to forward this state to applications? - // XXX: also how do we expose state restoration to apps? - warn!("TODO: forward saveState notification to application"); + // NOTE: The SaveSaver handle for state persistence is intentionally + // discarded. Applications receive SaveStateRequested as a notification + // only; actual state writing via SaveSaver is not yet supported. + if let Some(ref mut h) = *self.event_loop.borrow_mut() { + h(event::Event::SaveStateRequested); + } } + // OHOS lifecycle: Pause = about to enter background (surface still alive). + // Mapped to Suspended for cross-platform consistency with Android/iOS. + // Note: this fires earlier than a full "Stop/Hidden" state. MainEvent::Pause => { - debug!("App Paused - stopped running"); - // TODO: This is incorrect - will be solved in https://github.com/rust-windowing/winit/pull/3897 - // self.running = false; + if let Some(ref mut h) = *self.event_loop.borrow_mut() { + h(event::Event::Suspended); + } + } + // OHOS lifecycle: Stop = ability fully hidden/backgrounded (StageEventType::Hidden). + // Also mapped to Suspended — apps see a second Suspended when fully backgrounded. + MainEvent::Stop => { + if let Some(ref mut h) = *self.event_loop.borrow_mut() { + h(event::Event::Suspended); + } } MainEvent::WindowDestroy => { if let Some(ref mut h) = *self.event_loop.borrow_mut() {