mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-12-12 14:25:54 +00:00
refactor: unify surface registry
This commit is contained in:
parent
8e96e49c76
commit
ebc630b6dc
3 changed files with 230 additions and 47 deletions
|
|
@ -6,6 +6,7 @@ mod popup_builder;
|
|||
mod shell;
|
||||
mod shell_config;
|
||||
mod shell_runtime;
|
||||
mod surface_registry;
|
||||
mod system;
|
||||
pub mod value_conversion;
|
||||
|
||||
|
|
@ -37,9 +38,11 @@ pub use layer_surface::{LayerSurfaceHandle, ShellSurfaceConfigHandler};
|
|||
|
||||
pub use shell::{
|
||||
DEFAULT_COMPONENT_NAME, Shell, ShellBuilder, ShellEventContext, ShellEventLoopHandle,
|
||||
SurfaceConfigBuilder, SurfaceDefinition,
|
||||
SurfaceConfigBuilder,
|
||||
};
|
||||
|
||||
pub use surface_registry::{SurfaceDefinition, SurfaceEntry, SurfaceMetadata, SurfaceRegistry};
|
||||
|
||||
pub use shell_config::{CompiledUiSource, ShellConfig, SurfaceComponentConfig};
|
||||
|
||||
pub mod calloop {
|
||||
|
|
@ -71,7 +74,7 @@ pub mod prelude {
|
|||
PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, Shell, ShellBuilder,
|
||||
ShellConfig, ShellControl, ShellEventContext, ShellEventLoopHandle, ShellRuntime,
|
||||
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
|
||||
SurfaceHandle,
|
||||
SurfaceEntry, SurfaceHandle, SurfaceMetadata, SurfaceRegistry,
|
||||
};
|
||||
|
||||
pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::layer_surface::LayerSurfaceHandle;
|
|||
use crate::popup_builder::PopupBuilder;
|
||||
use crate::shell_config::{CompiledUiSource, ShellConfig};
|
||||
use crate::shell_runtime::ShellRuntime;
|
||||
use crate::surface_registry::{SurfaceDefinition, SurfaceEntry, SurfaceRegistry};
|
||||
use crate::system::{PopupCommand, ShellControl};
|
||||
use crate::value_conversion::IntoValue;
|
||||
use crate::{Error, Result};
|
||||
|
|
@ -25,18 +26,11 @@ use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
|||
use layer_shika_domain::value_objects::output_info::OutputInfo;
|
||||
use spin_on::spin_on;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub const DEFAULT_COMPONENT_NAME: &str = "Main";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SurfaceDefinition {
|
||||
pub component: String,
|
||||
pub config: SurfaceConfig,
|
||||
}
|
||||
|
||||
enum CompilationSource {
|
||||
File { path: PathBuf, compiler: Compiler },
|
||||
Source { code: String, compiler: Compiler },
|
||||
|
|
@ -224,8 +218,7 @@ type OutputDisconnectedHandler = Box<dyn Fn(OutputHandle)>;
|
|||
|
||||
pub struct Shell {
|
||||
inner: Rc<RefCell<dyn WaylandSystemOps>>,
|
||||
surfaces: HashMap<String, SurfaceDefinition>,
|
||||
surface_handles: HashMap<SurfaceHandle, String>,
|
||||
registry: SurfaceRegistry,
|
||||
compilation_result: Rc<CompilationResult>,
|
||||
popup_command_sender: channel::Sender<PopupCommand>,
|
||||
output_connected_handlers: Rc<RefCell<Vec<OutputConnectedHandler>>>,
|
||||
|
|
@ -401,16 +394,14 @@ impl Shell {
|
|||
|
||||
let (sender, receiver) = channel::channel();
|
||||
|
||||
let mut surfaces = HashMap::new();
|
||||
let mut surface_handles = HashMap::new();
|
||||
let mut registry = SurfaceRegistry::new();
|
||||
let handle = SurfaceHandle::new();
|
||||
surface_handles.insert(handle, definition.component.clone());
|
||||
surfaces.insert(definition.component.clone(), definition);
|
||||
let entry = SurfaceEntry::new(handle, definition.component.clone(), definition);
|
||||
registry.insert(entry)?;
|
||||
|
||||
let shell = Self {
|
||||
inner: Rc::clone(&inner_rc),
|
||||
surfaces,
|
||||
surface_handles,
|
||||
registry,
|
||||
compilation_result,
|
||||
popup_command_sender: sender,
|
||||
output_connected_handlers: Rc::new(RefCell::new(Vec::new())),
|
||||
|
|
@ -461,18 +452,16 @@ impl Shell {
|
|||
|
||||
let (sender, receiver) = channel::channel();
|
||||
|
||||
let mut surfaces = HashMap::new();
|
||||
let mut surface_handles = HashMap::new();
|
||||
let mut registry = SurfaceRegistry::new();
|
||||
for definition in definitions {
|
||||
let handle = SurfaceHandle::new();
|
||||
surface_handles.insert(handle, definition.component.clone());
|
||||
surfaces.insert(definition.component.clone(), definition);
|
||||
let entry = SurfaceEntry::new(handle, definition.component.clone(), definition);
|
||||
registry.insert(entry)?;
|
||||
}
|
||||
|
||||
let shell = Self {
|
||||
inner: Rc::clone(&inner_rc),
|
||||
surfaces,
|
||||
surface_handles,
|
||||
registry,
|
||||
compilation_result,
|
||||
popup_command_sender: sender,
|
||||
output_connected_handlers: Rc::new(RefCell::new(Vec::new())),
|
||||
|
|
@ -539,11 +528,11 @@ impl Shell {
|
|||
}
|
||||
|
||||
pub fn surface_names(&self) -> Vec<&str> {
|
||||
self.surfaces.keys().map(String::as_str).collect()
|
||||
self.registry.surface_names()
|
||||
}
|
||||
|
||||
pub fn has_surface(&self, name: &str) -> bool {
|
||||
self.surfaces.contains_key(name)
|
||||
self.registry.contains_name(name)
|
||||
}
|
||||
|
||||
pub fn event_loop_handle(&self) -> ShellEventLoopHandle {
|
||||
|
|
@ -553,7 +542,7 @@ impl Shell {
|
|||
pub fn run(&mut self) -> Result<()> {
|
||||
log::info!(
|
||||
"Starting Shell event loop with {} windows",
|
||||
self.surfaces.len()
|
||||
self.registry.len()
|
||||
);
|
||||
self.inner.borrow_mut().run()?;
|
||||
Ok(())
|
||||
|
|
@ -588,10 +577,8 @@ impl Shell {
|
|||
let handles = system.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);
|
||||
let entry = SurfaceEntry::new(surface_handle, definition.component.clone(), definition);
|
||||
self.registry.insert(entry)?;
|
||||
|
||||
log::info!(
|
||||
"Spawned surface with handle {:?}, created {} output instances",
|
||||
|
|
@ -603,20 +590,18 @@ impl Shell {
|
|||
}
|
||||
|
||||
pub fn despawn_surface(&mut self, handle: SurfaceHandle) -> Result<()> {
|
||||
let surface_name = self.surface_handles.remove(&handle).ok_or_else(|| {
|
||||
let entry = self.registry.remove(handle).ok_or_else(|| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: format!("Surface handle {:?} not found", handle),
|
||||
})
|
||||
})?;
|
||||
|
||||
self.surfaces.remove(&surface_name);
|
||||
|
||||
let mut system = self.inner.borrow_mut();
|
||||
system.despawn_surface(&surface_name)?;
|
||||
system.despawn_surface(&entry.name)?;
|
||||
|
||||
log::info!(
|
||||
"Despawned surface '{}' with handle {:?}",
|
||||
surface_name,
|
||||
entry.name,
|
||||
handle
|
||||
);
|
||||
|
||||
|
|
@ -644,21 +629,18 @@ impl Shell {
|
|||
}
|
||||
|
||||
pub fn get_surface_handle(&self, name: &str) -> Option<SurfaceHandle> {
|
||||
self.surface_handles
|
||||
.iter()
|
||||
.find(|(_, n)| n.as_str() == name)
|
||||
.map(|(h, _)| *h)
|
||||
self.registry.handle_by_name(name)
|
||||
}
|
||||
|
||||
pub fn get_surface_name(&self, handle: SurfaceHandle) -> Option<&str> {
|
||||
self.surface_handles.get(&handle).map(String::as_str)
|
||||
self.registry.name_by_handle(handle)
|
||||
}
|
||||
|
||||
pub fn with_surface<F, R>(&self, name: &str, f: F) -> Result<R>
|
||||
where
|
||||
F: FnOnce(&ComponentInstance) -> R,
|
||||
{
|
||||
if !self.surfaces.contains_key(name) {
|
||||
if !self.registry.contains_name(name) {
|
||||
return Err(Error::Domain(DomainError::Configuration {
|
||||
message: format!("Window '{}' not found", name),
|
||||
}));
|
||||
|
|
@ -684,7 +666,7 @@ impl Shell {
|
|||
{
|
||||
let system = self.inner.borrow();
|
||||
|
||||
for name in self.surfaces.keys() {
|
||||
for name in self.registry.surface_names() {
|
||||
for surface in system.app_state().surfaces_by_name(name) {
|
||||
f(name, surface.component_instance());
|
||||
}
|
||||
|
|
@ -732,7 +714,7 @@ impl Shell {
|
|||
F: Fn(ShellControl) -> R + 'static,
|
||||
R: IntoValue,
|
||||
{
|
||||
if !self.surfaces.contains_key(surface_name) {
|
||||
if !self.registry.contains_name(surface_name) {
|
||||
return Err(Error::Domain(DomainError::Configuration {
|
||||
message: format!("Window '{}' not found", surface_name),
|
||||
}));
|
||||
|
|
@ -773,7 +755,7 @@ impl Shell {
|
|||
F: Fn(&[Value], ShellControl) -> R + 'static,
|
||||
R: IntoValue,
|
||||
{
|
||||
if !self.surfaces.contains_key(surface_name) {
|
||||
if !self.registry.contains_name(surface_name) {
|
||||
return Err(Error::Domain(DomainError::Configuration {
|
||||
message: format!("Window '{}' not found", surface_name),
|
||||
}));
|
||||
|
|
@ -868,7 +850,7 @@ impl Shell {
|
|||
{
|
||||
let system = self.inner.borrow();
|
||||
|
||||
if self.surfaces.contains_key(surface_name) {
|
||||
if self.registry.contains_name(surface_name) {
|
||||
for surface in system.app_state().surfaces_by_name(surface_name) {
|
||||
let surface_handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
f(surface.component_instance(), surface_handle);
|
||||
|
|
@ -918,7 +900,7 @@ impl ShellRuntime for Shell {
|
|||
{
|
||||
let system = self.inner.borrow();
|
||||
|
||||
if self.surfaces.contains_key(name) {
|
||||
if self.registry.contains_name(name) {
|
||||
for surface in system.app_state().surfaces_by_name(name) {
|
||||
f(surface.component_instance());
|
||||
}
|
||||
|
|
@ -931,7 +913,7 @@ impl ShellRuntime for Shell {
|
|||
{
|
||||
let system = self.inner.borrow();
|
||||
|
||||
for name in self.surfaces.keys() {
|
||||
for name in self.registry.surface_names() {
|
||||
for surface in system.app_state().surfaces_by_name(name) {
|
||||
f(name, surface.component_instance());
|
||||
}
|
||||
|
|
|
|||
198
crates/composition/src/surface_registry.rs
Normal file
198
crates/composition/src/surface_registry.rs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
use crate::{Error, Result};
|
||||
use layer_shika_adapters::platform::slint_interpreter::ComponentInstance;
|
||||
use layer_shika_domain::config::SurfaceConfig;
|
||||
use layer_shika_domain::errors::DomainError;
|
||||
use layer_shika_domain::value_objects::handle::SurfaceHandle;
|
||||
use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SurfaceDefinition {
|
||||
pub component: String,
|
||||
pub config: SurfaceConfig,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SurfaceMetadata {
|
||||
pub spawn_order: usize,
|
||||
pub creation_timestamp: u64,
|
||||
}
|
||||
|
||||
pub struct SurfaceEntry {
|
||||
pub handle: SurfaceHandle,
|
||||
pub name: String,
|
||||
pub component: String,
|
||||
pub definition: SurfaceDefinition,
|
||||
pub output_instances: HashMap<OutputHandle, Rc<ComponentInstance>>,
|
||||
pub metadata: SurfaceMetadata,
|
||||
}
|
||||
|
||||
impl SurfaceEntry {
|
||||
pub fn new(handle: SurfaceHandle, name: String, definition: SurfaceDefinition) -> Self {
|
||||
let component = definition.component.clone();
|
||||
Self {
|
||||
handle,
|
||||
name,
|
||||
component,
|
||||
definition,
|
||||
output_instances: HashMap::new(),
|
||||
metadata: SurfaceMetadata::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_output_instance(&mut self, output: OutputHandle, instance: Rc<ComponentInstance>) {
|
||||
self.output_instances.insert(output, instance);
|
||||
}
|
||||
|
||||
pub fn remove_output_instance(
|
||||
&mut self,
|
||||
output: OutputHandle,
|
||||
) -> Option<Rc<ComponentInstance>> {
|
||||
self.output_instances.remove(&output)
|
||||
}
|
||||
|
||||
pub fn get_output_instance(&self, output: OutputHandle) -> Option<&Rc<ComponentInstance>> {
|
||||
self.output_instances.get(&output)
|
||||
}
|
||||
|
||||
pub fn outputs(&self) -> Vec<OutputHandle> {
|
||||
self.output_instances.keys().copied().collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SurfaceRegistry {
|
||||
entries: HashMap<SurfaceHandle, SurfaceEntry>,
|
||||
by_name: HashMap<String, SurfaceHandle>,
|
||||
by_component: HashMap<String, Vec<SurfaceHandle>>,
|
||||
next_spawn_order: usize,
|
||||
}
|
||||
|
||||
impl SurfaceRegistry {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
entries: HashMap::new(),
|
||||
by_name: HashMap::new(),
|
||||
by_component: HashMap::new(),
|
||||
next_spawn_order: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, mut entry: SurfaceEntry) -> Result<()> {
|
||||
if self.by_name.contains_key(&entry.name) {
|
||||
return Err(Error::Domain(DomainError::Configuration {
|
||||
message: format!("Surface with name '{}' already exists", entry.name),
|
||||
}));
|
||||
}
|
||||
|
||||
entry.metadata.spawn_order = self.next_spawn_order;
|
||||
self.next_spawn_order += 1;
|
||||
|
||||
let handle = entry.handle;
|
||||
let name = entry.name.clone();
|
||||
let component = entry.component.clone();
|
||||
|
||||
self.by_name.insert(name, handle);
|
||||
|
||||
self.by_component.entry(component).or_default().push(handle);
|
||||
|
||||
self.entries.insert(handle, entry);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, handle: SurfaceHandle) -> Option<SurfaceEntry> {
|
||||
let entry = self.entries.remove(&handle)?;
|
||||
|
||||
self.by_name.remove(&entry.name);
|
||||
|
||||
if let Some(handles) = self.by_component.get_mut(&entry.component) {
|
||||
handles.retain(|&h| h != handle);
|
||||
if handles.is_empty() {
|
||||
self.by_component.remove(&entry.component);
|
||||
}
|
||||
}
|
||||
|
||||
Some(entry)
|
||||
}
|
||||
|
||||
pub fn get(&self, handle: SurfaceHandle) -> Option<&SurfaceEntry> {
|
||||
self.entries.get(&handle)
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, handle: SurfaceHandle) -> Option<&mut SurfaceEntry> {
|
||||
self.entries.get_mut(&handle)
|
||||
}
|
||||
|
||||
pub fn by_name(&self, name: &str) -> Option<&SurfaceEntry> {
|
||||
self.by_name.get(name).and_then(|h| self.entries.get(h))
|
||||
}
|
||||
|
||||
pub fn by_name_mut(&mut self, name: &str) -> Option<&mut SurfaceEntry> {
|
||||
self.by_name.get(name).and_then(|h| self.entries.get_mut(h))
|
||||
}
|
||||
|
||||
pub fn handle_by_name(&self, name: &str) -> Option<SurfaceHandle> {
|
||||
self.by_name.get(name).copied()
|
||||
}
|
||||
|
||||
pub fn name_by_handle(&self, handle: SurfaceHandle) -> Option<&str> {
|
||||
self.entries.get(&handle).map(|e| e.name.as_str())
|
||||
}
|
||||
|
||||
pub fn by_component(&self, component: &str) -> Vec<&SurfaceEntry> {
|
||||
self.by_component
|
||||
.get(component)
|
||||
.map(|handles| handles.iter().filter_map(|h| self.entries.get(h)).collect())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn all(&self) -> impl Iterator<Item = &SurfaceEntry> {
|
||||
self.entries.values()
|
||||
}
|
||||
|
||||
pub fn all_mut(&mut self) -> impl Iterator<Item = &mut SurfaceEntry> {
|
||||
self.entries.values_mut()
|
||||
}
|
||||
|
||||
pub fn handles(&self) -> impl Iterator<Item = SurfaceHandle> + '_ {
|
||||
self.entries.keys().copied()
|
||||
}
|
||||
|
||||
pub fn outputs_for_surface(&self, handle: SurfaceHandle) -> Vec<OutputHandle> {
|
||||
self.entries
|
||||
.get(&handle)
|
||||
.map(SurfaceEntry::outputs)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn surface_names(&self) -> Vec<&str> {
|
||||
self.by_name.keys().map(String::as_str).collect()
|
||||
}
|
||||
|
||||
pub fn component_names(&self) -> Vec<&str> {
|
||||
self.by_component.keys().map(String::as_str).collect()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.entries.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
pub fn contains(&self, handle: SurfaceHandle) -> bool {
|
||||
self.entries.contains_key(&handle)
|
||||
}
|
||||
|
||||
pub fn contains_name(&self, name: &str) -> bool {
|
||||
self.by_name.contains_key(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SurfaceRegistry {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue