mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-12-12 16:35:56 +00:00
feat: explicit surface lifecycle management
This commit is contained in:
parent
f843d931e5
commit
318ac1439b
8 changed files with 178 additions and 330 deletions
|
|
@ -711,6 +711,42 @@ impl WaylandShellSystem {
|
||||||
pub fn app_state(&self) -> &AppState {
|
pub fn app_state(&self) -> &AppState {
|
||||||
&self.state
|
&self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn app_state_mut(&mut self) -> &mut AppState {
|
||||||
|
&mut self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_surface(&mut self, config: &ShellSurfaceConfig) -> Result<Vec<OutputHandle>> {
|
||||||
|
log::info!("Spawning new surface '{}'", config.name);
|
||||||
|
|
||||||
|
let mut handles = Vec::new();
|
||||||
|
|
||||||
|
for (output_handle, _surface) in self.state.outputs_with_handles() {
|
||||||
|
handles.push(output_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!(
|
||||||
|
"Surface '{}' would spawn on {} outputs (dynamic spawning not yet fully implemented)",
|
||||||
|
config.name,
|
||||||
|
handles.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(handles)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn despawn_surface(&mut self, surface_name: &str) -> Result<()> {
|
||||||
|
log::info!("Despawning surface '{}'", surface_name);
|
||||||
|
|
||||||
|
let removed = self.state.remove_surfaces_by_name(surface_name);
|
||||||
|
|
||||||
|
log::info!(
|
||||||
|
"Removed {} surface instances for '{}'",
|
||||||
|
removed.len(),
|
||||||
|
surface_name
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShellSystemPort for WaylandShellSystem {
|
impl ShellSystemPort for WaylandShellSystem {
|
||||||
|
|
|
||||||
|
|
@ -408,4 +408,25 @@ impl AppState {
|
||||||
.map(|(_, v)| v)
|
.map(|(_, v)| v)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_surfaces_by_name(&mut self, surface_name: &str) -> Vec<PerOutputSurface> {
|
||||||
|
let keys_to_remove: Vec<_> = self
|
||||||
|
.surfaces
|
||||||
|
.keys()
|
||||||
|
.filter(|k| k.surface_name == surface_name)
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut removed = Vec::new();
|
||||||
|
for key in keys_to_remove {
|
||||||
|
if let Some(surface) = self.surfaces.remove(&key) {
|
||||||
|
removed.push(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.surface_to_key
|
||||||
|
.retain(|_, k| k.surface_name != surface_name);
|
||||||
|
|
||||||
|
removed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ pub use layer_shika_domain::value_objects::popup_request::{
|
||||||
};
|
};
|
||||||
pub use popup_builder::PopupBuilder;
|
pub use popup_builder::PopupBuilder;
|
||||||
pub use shell_runtime::{DEFAULT_SURFACE_NAME, ShellRuntime};
|
pub use shell_runtime::{DEFAULT_SURFACE_NAME, ShellRuntime};
|
||||||
pub use system::{EventContext, EventLoopHandle, ShellControl, SingleSurfaceShell};
|
pub use system::{EventContext, EventLoopHandle, ShellControl};
|
||||||
pub use value_conversion::IntoValue;
|
pub use value_conversion::IntoValue;
|
||||||
|
|
||||||
pub use layer_surface::{LayerSurfaceHandle, ShellSurfaceConfigHandler};
|
pub use layer_surface::{LayerSurfaceHandle, ShellSurfaceConfigHandler};
|
||||||
|
|
@ -70,8 +70,8 @@ pub mod prelude {
|
||||||
OutputPolicy, OutputRegistry, PopupBuilder, PopupHandle, PopupPlacement,
|
OutputPolicy, OutputRegistry, PopupBuilder, PopupHandle, PopupPlacement,
|
||||||
PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, Shell, ShellBuilder,
|
PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, Shell, ShellBuilder,
|
||||||
ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
||||||
ShellSurfaceConfigHandler, SingleSurfaceShell, SurfaceComponentConfig, SurfaceConfigBuilder,
|
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
|
||||||
SurfaceDefinition, SurfaceHandle,
|
SurfaceHandle,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer};
|
pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer};
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ use layer_shika_domain::errors::DomainError;
|
||||||
use layer_shika_domain::prelude::{
|
use layer_shika_domain::prelude::{
|
||||||
AnchorEdges, KeyboardInteractivity, Layer, Margins, OutputPolicy, ScaleFactor, SurfaceDimension,
|
AnchorEdges, KeyboardInteractivity, Layer, Margins, OutputPolicy, ScaleFactor, SurfaceDimension,
|
||||||
};
|
};
|
||||||
|
use layer_shika_domain::value_objects::handle::SurfaceHandle;
|
||||||
use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
||||||
use layer_shika_domain::value_objects::output_info::OutputInfo;
|
use layer_shika_domain::value_objects::output_info::OutputInfo;
|
||||||
use spin_on::spin_on;
|
use spin_on::spin_on;
|
||||||
|
|
@ -218,11 +219,17 @@ impl SurfaceConfigBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OutputConnectedHandler = Box<dyn Fn(&OutputInfo)>;
|
||||||
|
type OutputDisconnectedHandler = Box<dyn Fn(OutputHandle)>;
|
||||||
|
|
||||||
pub struct Shell {
|
pub struct Shell {
|
||||||
inner: Rc<RefCell<ShellSystemFacade>>,
|
inner: Rc<RefCell<ShellSystemFacade>>,
|
||||||
surfaces: HashMap<String, SurfaceDefinition>,
|
surfaces: HashMap<String, SurfaceDefinition>,
|
||||||
|
surface_handles: HashMap<SurfaceHandle, String>,
|
||||||
compilation_result: Rc<CompilationResult>,
|
compilation_result: Rc<CompilationResult>,
|
||||||
popup_command_sender: channel::Sender<PopupCommand>,
|
popup_command_sender: channel::Sender<PopupCommand>,
|
||||||
|
output_connected_handlers: Rc<RefCell<Vec<OutputConnectedHandler>>>,
|
||||||
|
output_disconnected_handlers: Rc<RefCell<Vec<OutputDisconnectedHandler>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shell {
|
impl Shell {
|
||||||
|
|
@ -396,13 +403,19 @@ impl Shell {
|
||||||
let (sender, receiver) = channel::channel();
|
let (sender, receiver) = channel::channel();
|
||||||
|
|
||||||
let mut surfaces = HashMap::new();
|
let mut surfaces = HashMap::new();
|
||||||
|
let mut surface_handles = HashMap::new();
|
||||||
|
let handle = SurfaceHandle::new();
|
||||||
|
surface_handles.insert(handle, definition.component.clone());
|
||||||
surfaces.insert(definition.component.clone(), definition);
|
surfaces.insert(definition.component.clone(), definition);
|
||||||
|
|
||||||
let shell = Self {
|
let shell = Self {
|
||||||
inner: Rc::clone(&inner_rc),
|
inner: Rc::clone(&inner_rc),
|
||||||
surfaces,
|
surfaces,
|
||||||
|
surface_handles,
|
||||||
compilation_result,
|
compilation_result,
|
||||||
popup_command_sender: sender,
|
popup_command_sender: sender,
|
||||||
|
output_connected_handlers: Rc::new(RefCell::new(Vec::new())),
|
||||||
|
output_disconnected_handlers: Rc::new(RefCell::new(Vec::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
shell.setup_popup_command_handler(receiver)?;
|
shell.setup_popup_command_handler(receiver)?;
|
||||||
|
|
@ -451,15 +464,21 @@ impl Shell {
|
||||||
let (sender, receiver) = channel::channel();
|
let (sender, receiver) = channel::channel();
|
||||||
|
|
||||||
let mut surfaces = HashMap::new();
|
let mut surfaces = HashMap::new();
|
||||||
|
let mut surface_handles = HashMap::new();
|
||||||
for definition in definitions {
|
for definition in definitions {
|
||||||
|
let handle = SurfaceHandle::new();
|
||||||
|
surface_handles.insert(handle, definition.component.clone());
|
||||||
surfaces.insert(definition.component.clone(), definition);
|
surfaces.insert(definition.component.clone(), definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
let shell = Self {
|
let shell = Self {
|
||||||
inner: Rc::clone(&inner_rc),
|
inner: Rc::clone(&inner_rc),
|
||||||
surfaces,
|
surfaces,
|
||||||
|
surface_handles,
|
||||||
compilation_result,
|
compilation_result,
|
||||||
popup_command_sender: sender,
|
popup_command_sender: sender,
|
||||||
|
output_connected_handlers: Rc::new(RefCell::new(Vec::new())),
|
||||||
|
output_disconnected_handlers: Rc::new(RefCell::new(Vec::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
shell.setup_popup_command_handler(receiver)?;
|
shell.setup_popup_command_handler(receiver)?;
|
||||||
|
|
@ -542,6 +561,101 @@ impl Shell {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn spawn_surface(&mut self, definition: SurfaceDefinition) -> Result<Vec<SurfaceHandle>> {
|
||||||
|
let component_definition = self
|
||||||
|
.compilation_result
|
||||||
|
.component(&definition.component)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::Domain(DomainError::Configuration {
|
||||||
|
message: format!(
|
||||||
|
"Component '{}' not found in compilation result",
|
||||||
|
definition.component
|
||||||
|
),
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let wayland_config = WaylandSurfaceConfig::from_domain_config(
|
||||||
|
&definition.component,
|
||||||
|
component_definition,
|
||||||
|
Some(Rc::clone(&self.compilation_result)),
|
||||||
|
definition.config.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let shell_config = ShellSurfaceConfig {
|
||||||
|
name: definition.component.clone(),
|
||||||
|
config: wayland_config,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut facade = self.inner.borrow_mut();
|
||||||
|
let handles = facade.inner_mut().spawn_surface(&shell_config)?;
|
||||||
|
|
||||||
|
let surface_handle = SurfaceHandle::new();
|
||||||
|
self.surface_handles
|
||||||
|
.insert(surface_handle, definition.component.clone());
|
||||||
|
self.surfaces
|
||||||
|
.insert(definition.component.clone(), definition);
|
||||||
|
|
||||||
|
log::info!(
|
||||||
|
"Spawned surface with handle {:?}, created {} output instances",
|
||||||
|
surface_handle,
|
||||||
|
handles.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(vec![surface_handle])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn despawn_surface(&mut self, handle: SurfaceHandle) -> Result<()> {
|
||||||
|
let surface_name = self.surface_handles.remove(&handle).ok_or_else(|| {
|
||||||
|
Error::Domain(DomainError::Configuration {
|
||||||
|
message: format!("Surface handle {:?} not found", handle),
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.surfaces.remove(&surface_name);
|
||||||
|
|
||||||
|
let mut facade = self.inner.borrow_mut();
|
||||||
|
facade.inner_mut().despawn_surface(&surface_name)?;
|
||||||
|
|
||||||
|
log::info!(
|
||||||
|
"Despawned surface '{}' with handle {:?}",
|
||||||
|
surface_name,
|
||||||
|
handle
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_output_connected<F>(&mut self, handler: F) -> Result<()>
|
||||||
|
where
|
||||||
|
F: Fn(&OutputInfo) + 'static,
|
||||||
|
{
|
||||||
|
self.output_connected_handlers
|
||||||
|
.borrow_mut()
|
||||||
|
.push(Box::new(handler));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_output_disconnected<F>(&mut self, handler: F) -> Result<()>
|
||||||
|
where
|
||||||
|
F: Fn(OutputHandle) + 'static,
|
||||||
|
{
|
||||||
|
self.output_disconnected_handlers
|
||||||
|
.borrow_mut()
|
||||||
|
.push(Box::new(handler));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_surface_handle(&self, name: &str) -> Option<SurfaceHandle> {
|
||||||
|
self.surface_handles
|
||||||
|
.iter()
|
||||||
|
.find(|(_, n)| n.as_str() == name)
|
||||||
|
.map(|(h, _)| *h)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_surface_name(&self, handle: SurfaceHandle) -> Option<&str> {
|
||||||
|
self.surface_handles.get(&handle).map(String::as_str)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_surface<F, R>(&self, name: &str, f: F) -> Result<R>
|
pub fn with_surface<F, R>(&self, name: &str, f: F) -> Result<R>
|
||||||
where
|
where
|
||||||
F: FnOnce(&ComponentInstance) -> R,
|
F: FnOnce(&ComponentInstance) -> R,
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
use crate::event_loop::{EventLoopHandleBase, FromAppState};
|
use crate::event_loop::{EventLoopHandleBase, FromAppState};
|
||||||
use crate::shell_runtime::{DEFAULT_SURFACE_NAME, ShellRuntime};
|
|
||||||
use crate::value_conversion::IntoValue;
|
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
use layer_shika_adapters::errors::EventLoopError;
|
|
||||||
use layer_shika_adapters::platform::calloop::channel;
|
use layer_shika_adapters::platform::calloop::channel;
|
||||||
use layer_shika_adapters::platform::slint::ComponentHandle;
|
use layer_shika_adapters::platform::slint::ComponentHandle;
|
||||||
use layer_shika_adapters::platform::slint_interpreter::{
|
use layer_shika_adapters::platform::slint_interpreter::{
|
||||||
CompilationResult, ComponentDefinition, ComponentInstance, Value,
|
CompilationResult, ComponentDefinition, ComponentInstance, Value,
|
||||||
};
|
};
|
||||||
use layer_shika_adapters::{
|
use layer_shika_adapters::{AppState, PopupManager, SurfaceState};
|
||||||
AppState, PopupManager, ShellSystemFacade, SurfaceState, WaylandSurfaceConfig,
|
|
||||||
};
|
|
||||||
use layer_shika_domain::config::SurfaceConfig;
|
|
||||||
use layer_shika_domain::entities::output_registry::OutputRegistry;
|
use layer_shika_domain::entities::output_registry::OutputRegistry;
|
||||||
use layer_shika_domain::errors::DomainError;
|
use layer_shika_domain::errors::DomainError;
|
||||||
use layer_shika_domain::value_objects::dimensions::PopupDimensions;
|
use layer_shika_domain::value_objects::dimensions::PopupDimensions;
|
||||||
|
|
@ -22,7 +16,6 @@ use layer_shika_domain::value_objects::popup_request::{
|
||||||
PopupHandle, PopupPlacement, PopupRequest, PopupSize,
|
PopupHandle, PopupPlacement, PopupRequest, PopupSize,
|
||||||
};
|
};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub enum PopupCommand {
|
pub enum PopupCommand {
|
||||||
|
|
@ -551,316 +544,3 @@ impl EventContext<'_> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SingleSurfaceShell {
|
|
||||||
inner: Rc<RefCell<ShellSystemFacade>>,
|
|
||||||
popup_command_sender: channel::Sender<PopupCommand>,
|
|
||||||
surface_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl SingleSurfaceShell {
|
|
||||||
pub(crate) fn new(
|
|
||||||
component_definition: ComponentDefinition,
|
|
||||||
compilation_result: Option<Rc<CompilationResult>>,
|
|
||||||
config: SurfaceConfig,
|
|
||||||
) -> Result<Self> {
|
|
||||||
let wayland_config = WaylandSurfaceConfig::from_domain_config(
|
|
||||||
"default",
|
|
||||||
component_definition,
|
|
||||||
compilation_result,
|
|
||||||
config,
|
|
||||||
);
|
|
||||||
let inner = layer_shika_adapters::WaylandShellSystem::new(&wayland_config)?;
|
|
||||||
let facade = ShellSystemFacade::new(inner);
|
|
||||||
let inner_rc = Rc::new(RefCell::new(facade));
|
|
||||||
|
|
||||||
let (sender, receiver) = channel::channel();
|
|
||||||
|
|
||||||
let shell = Self {
|
|
||||||
inner: Rc::clone(&inner_rc),
|
|
||||||
popup_command_sender: sender,
|
|
||||||
surface_name: DEFAULT_SURFACE_NAME.to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
shell.setup_popup_command_handler(receiver)?;
|
|
||||||
|
|
||||||
Ok(shell)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_surface_name(mut self, name: impl Into<String>) -> Self {
|
|
||||||
self.surface_name = name.into();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn surface_name(&self) -> &str {
|
|
||||||
&self.surface_name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_popup_command_handler(&self, receiver: channel::Channel<PopupCommand>) -> Result<()> {
|
|
||||||
let loop_handle = self.inner.borrow().inner_ref().event_loop_handle();
|
|
||||||
let control = self.control();
|
|
||||||
|
|
||||||
loop_handle
|
|
||||||
.insert_source(receiver, move |event, (), app_state| {
|
|
||||||
if let channel::Event::Msg(command) = event {
|
|
||||||
let mut shell_context = EventContext { app_state };
|
|
||||||
|
|
||||||
match command {
|
|
||||||
PopupCommand::Show(request) => {
|
|
||||||
if let Err(e) =
|
|
||||||
shell_context.show_popup(&request, Some(control.clone()))
|
|
||||||
{
|
|
||||||
log::error!("Failed to show popup: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PopupCommand::Close(handle) => {
|
|
||||||
if let Err(e) = shell_context.close_popup(handle) {
|
|
||||||
log::error!("Failed to close popup: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PopupCommand::Resize {
|
|
||||||
handle,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
} => {
|
|
||||||
if let Err(e) = shell_context.resize_popup(handle, width, height) {
|
|
||||||
log::error!("Failed to resize popup: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map_err(|e| {
|
|
||||||
Error::Adapter(
|
|
||||||
EventLoopError::InsertSource {
|
|
||||||
message: format!("Failed to setup popup command handler: {e:?}"),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn control(&self) -> ShellControl {
|
|
||||||
ShellControl {
|
|
||||||
sender: self.popup_command_sender.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn event_loop_handle(&self) -> EventLoopHandle {
|
|
||||||
EventLoopHandle::new(Rc::downgrade(&self.inner))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on<F, R>(&self, callback_name: &str, handler: F) -> Result<()>
|
|
||||||
where
|
|
||||||
F: Fn(ShellControl) -> R + 'static,
|
|
||||||
R: IntoValue,
|
|
||||||
{
|
|
||||||
let control = self.control();
|
|
||||||
let handler = Rc::new(handler);
|
|
||||||
self.with_all_component_instances(|instance| {
|
|
||||||
let handler_rc = Rc::clone(&handler);
|
|
||||||
let control_clone = control.clone();
|
|
||||||
if let Err(e) = instance.set_callback(callback_name, move |_args| {
|
|
||||||
handler_rc(control_clone.clone()).into_value()
|
|
||||||
}) {
|
|
||||||
log::error!(
|
|
||||||
"Failed to register callback '{}' on component: {}",
|
|
||||||
callback_name,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_with_args<F, R>(&self, callback_name: &str, handler: F) -> Result<()>
|
|
||||||
where
|
|
||||||
F: Fn(&[Value], ShellControl) -> R + 'static,
|
|
||||||
R: IntoValue,
|
|
||||||
{
|
|
||||||
let control = self.control();
|
|
||||||
let handler = Rc::new(handler);
|
|
||||||
self.with_all_component_instances(|instance| {
|
|
||||||
let handler_rc = Rc::clone(&handler);
|
|
||||||
let control_clone = control.clone();
|
|
||||||
if let Err(e) = instance.set_callback(callback_name, move |args| {
|
|
||||||
handler_rc(args, control_clone.clone()).into_value()
|
|
||||||
}) {
|
|
||||||
log::error!(
|
|
||||||
"Failed to register callback '{}' on component: {}",
|
|
||||||
callback_name,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_for_output<F, R>(
|
|
||||||
&self,
|
|
||||||
output: OutputHandle,
|
|
||||||
callback_name: &str,
|
|
||||||
handler: F,
|
|
||||||
) -> Result<()>
|
|
||||||
where
|
|
||||||
F: Fn(ShellControl) -> R + 'static,
|
|
||||||
R: IntoValue,
|
|
||||||
{
|
|
||||||
let control = self.control();
|
|
||||||
self.with_output(output, |instance| {
|
|
||||||
let control_clone = control.clone();
|
|
||||||
if let Err(e) = instance.set_callback(callback_name, move |_args| {
|
|
||||||
handler(control_clone.clone()).into_value()
|
|
||||||
}) {
|
|
||||||
log::error!(
|
|
||||||
"Failed to register callback '{}' on output {:?}: {}",
|
|
||||||
callback_name,
|
|
||||||
output,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_for_output_with_args<F, R>(
|
|
||||||
&self,
|
|
||||||
output: OutputHandle,
|
|
||||||
callback_name: &str,
|
|
||||||
handler: F,
|
|
||||||
) -> Result<()>
|
|
||||||
where
|
|
||||||
F: Fn(&[Value], ShellControl) -> R + 'static,
|
|
||||||
R: IntoValue,
|
|
||||||
{
|
|
||||||
let control = self.control();
|
|
||||||
self.with_output(output, |instance| {
|
|
||||||
let control_clone = control.clone();
|
|
||||||
if let Err(e) = instance.set_callback(callback_name, move |args| {
|
|
||||||
handler(args, control_clone.clone()).into_value()
|
|
||||||
}) {
|
|
||||||
log::error!(
|
|
||||||
"Failed to register callback '{}' on output {:?}: {}",
|
|
||||||
callback_name,
|
|
||||||
output,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(&mut self) -> Result<()> {
|
|
||||||
self.inner.borrow_mut().run()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_component_instance<F, R>(&self, f: F) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&ComponentInstance) -> R,
|
|
||||||
{
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let instance = facade.component_instance()?;
|
|
||||||
Ok(f(instance))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_all_component_instances<F>(&self, mut f: F)
|
|
||||||
where
|
|
||||||
F: FnMut(&ComponentInstance),
|
|
||||||
{
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
for surface in system.app_state().all_outputs() {
|
|
||||||
f(surface.component_instance());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_output<F, R>(&self, handle: OutputHandle, f: F) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&ComponentInstance) -> R,
|
|
||||||
{
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
let window = system
|
|
||||||
.app_state()
|
|
||||||
.get_output_by_handle(handle)
|
|
||||||
.ok_or_else(|| {
|
|
||||||
Error::Domain(DomainError::Configuration {
|
|
||||||
message: format!("Output with handle {:?} not found", handle),
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
Ok(f(window.component_instance()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_all_outputs<F>(&self, mut f: F)
|
|
||||||
where
|
|
||||||
F: FnMut(OutputHandle, &ComponentInstance),
|
|
||||||
{
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
for (handle, surface) in system.app_state().outputs_with_handles() {
|
|
||||||
f(handle, surface.component_instance());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_output_info(&self, handle: OutputHandle) -> Option<OutputInfo> {
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
system.app_state().get_output_info(handle).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn all_output_info(&self) -> Vec<OutputInfo> {
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
system.app_state().all_output_info().cloned().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn output_registry(&self) -> OutputRegistry {
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
system.app_state().output_registry().clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ShellRuntime for SingleSurfaceShell {
|
|
||||||
type LoopHandle = EventLoopHandle;
|
|
||||||
type Context<'a> = EventContext<'a>;
|
|
||||||
|
|
||||||
fn event_loop_handle(&self) -> Self::LoopHandle {
|
|
||||||
EventLoopHandle::new(Rc::downgrade(&self.inner))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_component<F>(&self, _name: &str, mut f: F)
|
|
||||||
where
|
|
||||||
F: FnMut(&ComponentInstance),
|
|
||||||
{
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
for surface in system.app_state().all_outputs() {
|
|
||||||
f(surface.component_instance());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_all_components<F>(&self, mut f: F)
|
|
||||||
where
|
|
||||||
F: FnMut(&str, &ComponentInstance),
|
|
||||||
{
|
|
||||||
let facade = self.inner.borrow();
|
|
||||||
let system = facade.inner_ref();
|
|
||||||
for surface in system.app_state().all_outputs() {
|
|
||||||
f(&self.surface_name, surface.component_instance());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&mut self) -> Result<()> {
|
|
||||||
self.inner.borrow_mut().run()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -123,8 +123,7 @@ pub use layer_shika_composition::{Error, Handle, Result, SurfaceHandle};
|
||||||
pub use shell::{
|
pub use shell::{
|
||||||
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
|
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
|
||||||
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
||||||
ShellSurfaceConfigHandler, SingleSurfaceShell, SurfaceComponentConfig, SurfaceConfigBuilder,
|
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
|
||||||
SurfaceDefinition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use window::{
|
pub use window::{
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@
|
||||||
pub use crate::shell::{
|
pub use crate::shell::{
|
||||||
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
|
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
|
||||||
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
||||||
ShellSurfaceConfigHandler, SingleSurfaceShell, SurfaceComponentConfig, SurfaceConfigBuilder,
|
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
|
||||||
SurfaceDefinition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::window::{
|
pub use crate::window::{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
pub use layer_shika_composition::{
|
pub use layer_shika_composition::{
|
||||||
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
|
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
|
||||||
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
||||||
ShellSurfaceConfigHandler, SingleSurfaceShell, SurfaceComponentConfig, SurfaceConfigBuilder,
|
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
|
||||||
SurfaceDefinition,
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue