More text improvements, performance enhancements, input handling, text selection, wl cursors
This commit is contained in:
@@ -4,6 +4,7 @@ use ruin_reactivity::{EffectHandle, effect};
|
||||
|
||||
use crate::platform::{PlatformClosed, PlatformEvent, PlatformProxy, PlatformRuntime};
|
||||
use crate::scene::SceneSnapshot;
|
||||
use crate::tree::CursorIcon;
|
||||
use crate::window::{WindowId, WindowSpec, WindowUpdate};
|
||||
|
||||
/// High-level UI-side owner of platform event consumption.
|
||||
@@ -39,11 +40,13 @@ impl std::fmt::Display for EventStreamClosed {
|
||||
impl std::error::Error for EventStreamClosed {}
|
||||
|
||||
impl UiRuntime {
|
||||
pub fn from_platform(platform: PlatformRuntime) -> Self {
|
||||
Self { platform }
|
||||
}
|
||||
|
||||
/// Creates a UI runtime backed by the headless prototype backend.
|
||||
pub fn headless() -> Self {
|
||||
Self {
|
||||
platform: PlatformRuntime::headless(),
|
||||
}
|
||||
Self::from_platform(PlatformRuntime::headless())
|
||||
}
|
||||
|
||||
/// Returns a cloneable proxy for low-level platform commands.
|
||||
@@ -65,6 +68,11 @@ impl UiRuntime {
|
||||
self.platform.next_event().await
|
||||
}
|
||||
|
||||
/// Drains any platform events that are already queued locally.
|
||||
pub fn take_pending_events(&mut self) -> Vec<PlatformEvent> {
|
||||
self.platform.take_pending_events()
|
||||
}
|
||||
|
||||
/// Waits until an event matches `predicate`.
|
||||
pub async fn wait_for_event_matching(
|
||||
&mut self,
|
||||
@@ -100,11 +108,32 @@ impl WindowController {
|
||||
self.proxy.replace_scene(self.id, scene)
|
||||
}
|
||||
|
||||
/// Copies plain text to the platform primary-selection buffer for this window.
|
||||
pub fn set_primary_selection_text(
|
||||
&self,
|
||||
text: impl Into<String>,
|
||||
) -> Result<(), PlatformClosed> {
|
||||
self.proxy.set_primary_selection_text(self.id, text)
|
||||
}
|
||||
|
||||
/// Updates the platform cursor icon for this window.
|
||||
pub fn set_cursor_icon(&self, cursor: CursorIcon) -> Result<(), PlatformClosed> {
|
||||
self.proxy.set_cursor_icon(self.id, cursor)
|
||||
}
|
||||
|
||||
/// Emits a close-request event for this window.
|
||||
pub fn emit_close_requested(&self) -> Result<(), PlatformClosed> {
|
||||
self.proxy.emit_close_requested(self.id)
|
||||
}
|
||||
|
||||
/// Delivers a pointer event for this window through the platform event stream.
|
||||
pub fn emit_pointer_event(
|
||||
&self,
|
||||
event: crate::interaction::PointerEvent,
|
||||
) -> Result<(), PlatformClosed> {
|
||||
self.proxy.emit_pointer_event(self.id, event)
|
||||
}
|
||||
|
||||
/// Attaches a reactive effect that rebuilds and replaces the window scene whenever dependent UI
|
||||
/// state changes.
|
||||
pub fn attach_scene_effect(
|
||||
@@ -127,6 +156,7 @@ mod tests {
|
||||
use crate::platform::PlatformEvent;
|
||||
use crate::scene::{Color, Point, PreparedText, Rect, SceneSnapshot, UiSize};
|
||||
use crate::window::{WindowSpec, WindowUpdate};
|
||||
use crate::{PointerEvent, PointerEventKind};
|
||||
use ruin_runtime::{current_thread_handle, queue_future, run};
|
||||
use std::future::Future;
|
||||
|
||||
@@ -235,4 +265,49 @@ mod tests {
|
||||
ui.shutdown().expect("shutdown should queue");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn window_controller_emits_pointer_events_through_runtime() {
|
||||
run_async_test(async move {
|
||||
let mut ui = UiRuntime::headless();
|
||||
let window = ui
|
||||
.create_window(WindowSpec::new("pointer-events").visible(true))
|
||||
.expect("window should be created");
|
||||
|
||||
let _ = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(event, PlatformEvent::Opened { window_id } if *window_id == window.id())
|
||||
})
|
||||
.await
|
||||
.expect("window should open before pointer delivery");
|
||||
|
||||
window
|
||||
.emit_pointer_event(PointerEvent::new(
|
||||
0,
|
||||
Point::new(24.0, 32.0),
|
||||
PointerEventKind::Move,
|
||||
))
|
||||
.expect("pointer event should queue");
|
||||
|
||||
let event = ui
|
||||
.wait_for_event_matching(|event| {
|
||||
matches!(
|
||||
event,
|
||||
PlatformEvent::Pointer { window_id, .. } if *window_id == window.id()
|
||||
)
|
||||
})
|
||||
.await
|
||||
.expect("pointer event should be delivered");
|
||||
|
||||
assert_eq!(
|
||||
event,
|
||||
PlatformEvent::Pointer {
|
||||
window_id: window.id(),
|
||||
event: PointerEvent::new(0, Point::new(24.0, 32.0), PointerEventKind::Move),
|
||||
}
|
||||
);
|
||||
|
||||
ui.shutdown().expect("shutdown should queue");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user