refactor: migrate to selector system for surface and output

This commit is contained in:
drendog 2025-12-11 03:19:56 +01:00
parent 0d5a350f53
commit dc950833ea
Signed by: dwenya
GPG key ID: 8DD77074645332D0
10 changed files with 589 additions and 275 deletions

View file

@ -3,6 +3,8 @@
mod event_loop;
mod layer_surface;
mod popup_builder;
mod selector;
mod selection;
mod shell;
mod shell_config;
mod shell_runtime;
@ -32,6 +34,8 @@ pub use layer_shika_domain::value_objects::popup_request::{
};
pub use layer_surface::{LayerSurfaceHandle, ShellSurfaceConfigHandler};
pub use popup_builder::PopupBuilder;
pub use selector::{Output, Selector, Surface, SurfaceInfo};
pub use selection::Selection;
pub use shell_runtime::{DEFAULT_SURFACE_NAME, ShellRuntime};
pub use system::{EventDispatchContext, ShellControl, SurfaceControlHandle};
pub use value_conversion::IntoValue;
@ -66,13 +70,13 @@ pub mod prelude {
pub use crate::{
AnchorEdges, AnchorStrategy, CompiledUiSource, DEFAULT_COMPONENT_NAME,
DEFAULT_SURFACE_NAME, EventDispatchContext, EventLoopHandle, Handle, IntoValue,
KeyboardInteractivity, Layer, LayerSurfaceHandle, OutputGeometry, OutputHandle, OutputInfo,
OutputPolicy, OutputRegistry, PopupBuilder, PopupHandle, PopupPlacement,
PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, Shell, ShellBuilder,
ShellConfig, ShellControl, ShellEventContext, ShellEventLoop, ShellRuntime,
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder,
SurfaceControlHandle, SurfaceDefinition, SurfaceEntry, SurfaceHandle, SurfaceMetadata,
SurfaceRegistry,
KeyboardInteractivity, Layer, LayerSurfaceHandle, Output, OutputGeometry, OutputHandle,
OutputInfo, OutputPolicy, OutputRegistry, PopupBuilder, PopupHandle, PopupPlacement,
PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, Selection, Selector,
Shell, ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellEventLoop,
ShellRuntime, ShellSurfaceConfigHandler, Surface, SurfaceComponentConfig,
SurfaceConfigBuilder, SurfaceControlHandle, SurfaceDefinition, SurfaceEntry, SurfaceHandle,
SurfaceInfo, SurfaceMetadata, SurfaceRegistry,
};
pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer};

View file

@ -0,0 +1,96 @@
use crate::{
Error, LayerSurfaceHandle, Shell,
selector::{Selector, SurfaceInfo},
slint_interpreter::{ComponentInstance, Value},
};
use layer_shika_domain::errors::DomainError;
pub struct Selection<'a> {
shell: &'a Shell,
selector: Selector,
}
impl<'a> Selection<'a> {
pub(crate) fn new(shell: &'a Shell, selector: Selector) -> Self {
Self { shell, selector }
}
pub fn on_callback<F, R>(&self, callback_name: &str, handler: F)
where
F: Fn(crate::ShellControl) -> R + Clone + 'static,
R: crate::IntoValue,
{
self.shell
.on_internal(&self.selector, callback_name, handler);
}
pub fn on_callback_with_args<F, R>(&self, callback_name: &str, handler: F)
where
F: Fn(&[Value], crate::ShellControl) -> R + Clone + 'static,
R: crate::IntoValue,
{
self.shell
.on_with_args_internal(&self.selector, callback_name, handler);
}
pub fn with_component<F>(&self, mut f: F)
where
F: FnMut(&ComponentInstance),
{
self.shell.with_selected(&self.selector, |_, component| {
f(component);
});
}
pub fn set_property(&self, name: &str, value: &Value) -> Result<(), Error> {
let mut result = Ok(());
self.shell.with_selected(&self.selector, |_, component| {
if let Err(e) = component.set_property(name, value.clone()) {
log::error!("Failed to set property '{}': {}", name, e);
result = Err(Error::Domain(DomainError::Configuration {
message: format!("Failed to set property '{}': {}", name, e),
}));
}
});
result
}
pub fn get_property(&self, name: &str) -> Result<Vec<Value>, Error> {
let mut values = Vec::new();
let mut result = Ok(());
self.shell.with_selected(&self.selector, |_, component| {
match component.get_property(name) {
Ok(value) => values.push(value),
Err(e) => {
log::error!("Failed to get property '{}': {}", name, e);
result = Err(Error::Domain(DomainError::Configuration {
message: format!("Failed to get property '{}': {}", name, e),
}));
}
}
});
result.map(|()| values)
}
pub fn configure<F>(&self, mut f: F)
where
F: FnMut(&ComponentInstance, LayerSurfaceHandle<'_>),
{
self.shell
.configure_selected(&self.selector, |component, handle| {
f(component, handle);
});
}
pub fn count(&self) -> usize {
self.shell.count_selected(&self.selector)
}
pub fn is_empty(&self) -> bool {
self.count() == 0
}
pub fn info(&self) -> Vec<SurfaceInfo> {
self.shell.get_selected_info(&self.selector)
}
}

View file

@ -0,0 +1,180 @@
use crate::{OutputHandle, OutputInfo};
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct SurfaceInfo {
pub name: String,
pub output: OutputHandle,
}
#[derive(Clone)]
pub enum Surface {
All,
Named(String),
Any(Vec<String>),
Filter(Arc<dyn Fn(&SurfaceInfo) -> bool + Send + Sync>),
}
impl Surface {
pub fn all() -> Self {
Self::All
}
pub fn named(name: impl Into<String>) -> Self {
Self::Named(name.into())
}
pub fn any(names: impl IntoIterator<Item = impl Into<String>>) -> Self {
Self::Any(names.into_iter().map(Into::into).collect())
}
pub fn matching<F>(predicate: F) -> Self
where
F: Fn(&SurfaceInfo) -> bool + Send + Sync + 'static,
{
Self::Filter(Arc::new(predicate))
}
pub fn on(self, output: Output) -> Selector {
Selector {
surface: self,
output,
}
}
pub(crate) fn matches(&self, info: &SurfaceInfo) -> bool {
match self {
Self::All => true,
Self::Named(name) => &info.name == name,
Self::Any(names) => names.iter().any(|name| name == &info.name),
Self::Filter(predicate) => predicate(info),
}
}
}
impl Debug for Surface {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::All => write!(f, "Surface::All"),
Self::Named(name) => write!(f, "Surface::Named({:?})", name),
Self::Any(names) => write!(f, "Surface::Any({:?})", names),
Self::Filter(_) => write!(f, "Surface::Filter(<fn>)"),
}
}
}
#[derive(Clone)]
pub enum Output {
All,
Primary,
Active,
Handle(OutputHandle),
Named(String),
Filter(Arc<dyn Fn(&OutputInfo) -> bool + Send + Sync>),
}
impl Output {
pub fn all() -> Self {
Self::All
}
pub fn primary() -> Self {
Self::Primary
}
pub fn active() -> Self {
Self::Active
}
pub fn handle(handle: OutputHandle) -> Self {
Self::Handle(handle)
}
pub fn named(name: impl Into<String>) -> Self {
Self::Named(name.into())
}
pub fn matching<F>(predicate: F) -> Self
where
F: Fn(&OutputInfo) -> bool + Send + Sync + 'static,
{
Self::Filter(Arc::new(predicate))
}
pub(crate) fn matches(
&self,
handle: OutputHandle,
info: Option<&OutputInfo>,
primary: Option<OutputHandle>,
active: Option<OutputHandle>,
) -> bool {
match self {
Self::All => true,
Self::Primary => primary == Some(handle),
Self::Active => active == Some(handle),
Self::Handle(h) => *h == handle,
Self::Named(name) => info.is_some_and(|i| i.name() == Some(name.as_str())),
Self::Filter(predicate) => info.is_some_and(|i| predicate(i)),
}
}
}
impl Debug for Output {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::All => write!(f, "Output::All"),
Self::Primary => write!(f, "Output::Primary"),
Self::Active => write!(f, "Output::Active"),
Self::Handle(h) => write!(f, "Output::Handle({:?})", h),
Self::Named(name) => write!(f, "Output::Named({:?})", name),
Self::Filter(_) => write!(f, "Output::Filter(<fn>)"),
}
}
}
#[derive(Clone, Debug)]
pub struct Selector {
pub surface: Surface,
pub output: Output,
}
impl Selector {
pub fn all() -> Self {
Self {
surface: Surface::All,
output: Output::All,
}
}
pub(crate) fn matches(
&self,
surface_info: &SurfaceInfo,
output_info: Option<&OutputInfo>,
primary: Option<OutputHandle>,
active: Option<OutputHandle>,
) -> bool {
self.surface.matches(surface_info)
&& self
.output
.matches(surface_info.output, output_info, primary, active)
}
}
impl From<Surface> for Selector {
fn from(surface: Surface) -> Self {
Self {
surface,
output: Output::All,
}
}
}
impl From<Output> for Selector {
fn from(output: Output) -> Self {
Self {
surface: Surface::All,
output,
}
}
}

View file

@ -828,167 +828,6 @@ impl Shell {
PopupBuilder::new(self, component_name.into())
}
pub fn on<F, R>(&self, surface_name: &str, callback_name: &str, handler: F) -> Result<()>
where
F: Fn(ShellControl) -> R + 'static,
R: IntoValue,
{
if !self.registry.contains_name(surface_name) {
return Err(Error::Domain(DomainError::Configuration {
message: format!("Window '{}' not found", surface_name),
}));
}
let control = self.control();
let handler = Rc::new(handler);
let system = self.inner.borrow();
for surface in system.app_state().surfaces_by_name(surface_name) {
let handler_rc = Rc::clone(&handler);
let control_clone = control.clone();
if let Err(e) = surface
.component_instance()
.set_callback(callback_name, move |_args| {
handler_rc(control_clone.clone()).into_value()
})
{
log::error!(
"Failed to register callback '{}' on surface '{}': {}",
callback_name,
surface_name,
e
);
}
}
Ok(())
}
pub fn on_with_args<F, R>(
&self,
surface_name: &str,
callback_name: &str,
handler: F,
) -> Result<()>
where
F: Fn(&[Value], ShellControl) -> R + 'static,
R: IntoValue,
{
if !self.registry.contains_name(surface_name) {
return Err(Error::Domain(DomainError::Configuration {
message: format!("Window '{}' not found", surface_name),
}));
}
let control = self.control();
let handler = Rc::new(handler);
let system = self.inner.borrow();
for surface in system.app_state().surfaces_by_name(surface_name) {
let handler_rc = Rc::clone(&handler);
let control_clone = control.clone();
if let Err(e) = surface
.component_instance()
.set_callback(callback_name, move |args| {
handler_rc(args, control_clone.clone()).into_value()
})
{
log::error!(
"Failed to register callback '{}' on surface '{}': {}",
callback_name,
surface_name,
e
);
}
}
Ok(())
}
pub fn on_global<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);
let system = self.inner.borrow();
for surface in system.app_state().all_outputs() {
let handler_rc = Rc::clone(&handler);
let control_clone = control.clone();
if let Err(e) = surface
.component_instance()
.set_callback(callback_name, move |_args| {
handler_rc(control_clone.clone()).into_value()
})
{
log::error!(
"Failed to register global callback '{}': {}",
callback_name,
e
);
}
}
Ok(())
}
pub fn on_global_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);
let system = self.inner.borrow();
for surface in system.app_state().all_outputs() {
let handler_rc = Rc::clone(&handler);
let control_clone = control.clone();
if let Err(e) = surface
.component_instance()
.set_callback(callback_name, move |args| {
handler_rc(args, control_clone.clone()).into_value()
})
{
log::error!(
"Failed to register global callback '{}': {}",
callback_name,
e
);
}
}
Ok(())
}
pub fn apply_surface_config<F>(&self, surface_name: &str, f: F)
where
F: Fn(&ComponentInstance, LayerSurfaceHandle<'_>),
{
let system = self.inner.borrow();
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);
}
}
}
pub fn apply_global_config<F>(&self, f: F)
where
F: Fn(&ComponentInstance, LayerSurfaceHandle<'_>),
{
let system = self.inner.borrow();
for surface in system.app_state().all_outputs() {
let surface_handle = LayerSurfaceHandle::from_window_state(surface);
f(surface.component_instance(), surface_handle);
}
}
pub fn output_registry(&self) -> OutputRegistry {
let system = self.inner.borrow();
system.app_state().output_registry().clone()
@ -1003,6 +842,186 @@ impl Shell {
let system = self.inner.borrow();
system.app_state().all_output_info().cloned().collect()
}
pub fn select(&self, selector: impl Into<crate::Selector>) -> crate::Selection<'_> {
crate::Selection::new(self, selector.into())
}
fn get_output_handles(&self) -> (Option<OutputHandle>, Option<OutputHandle>) {
let registry = &self.output_registry();
(registry.primary_handle(), registry.active_handle())
}
pub(crate) fn on_internal<F, R>(
&self,
selector: &crate::Selector,
callback_name: &str,
handler: F,
) where
F: Fn(ShellControl) -> R + Clone + 'static,
R: IntoValue,
{
let control = self.control();
let handler = Rc::new(handler);
let system = self.inner.borrow();
let (primary, active) = self.get_output_handles();
for (key, surface) in system.app_state().surfaces_with_keys() {
let surface_info = crate::SurfaceInfo {
name: key.surface_name.clone(),
output: key.output_handle,
};
let output_info = system.app_state().get_output_info(key.output_handle);
if selector.matches(&surface_info, output_info, primary, active) {
let handler_rc = Rc::clone(&handler);
let control_clone = control.clone();
if let Err(e) = surface
.component_instance()
.set_callback(callback_name, move |_args| {
handler_rc(control_clone.clone()).into_value()
})
{
log::error!(
"Failed to register callback '{}' on surface '{}': {}",
callback_name,
key.surface_name,
e
);
}
}
}
}
pub(crate) fn on_with_args_internal<F, R>(
&self,
selector: &crate::Selector,
callback_name: &str,
handler: F,
) where
F: Fn(&[Value], ShellControl) -> R + Clone + 'static,
R: IntoValue,
{
let control = self.control();
let handler = Rc::new(handler);
let system = self.inner.borrow();
let (primary, active) = self.get_output_handles();
for (key, surface) in system.app_state().surfaces_with_keys() {
let surface_info = crate::SurfaceInfo {
name: key.surface_name.clone(),
output: key.output_handle,
};
let output_info = system.app_state().get_output_info(key.output_handle);
if selector.matches(&surface_info, output_info, primary, active) {
let handler_rc = Rc::clone(&handler);
let control_clone = control.clone();
if let Err(e) = surface
.component_instance()
.set_callback(callback_name, move |args| {
handler_rc(args, control_clone.clone()).into_value()
})
{
log::error!(
"Failed to register callback '{}' on surface '{}': {}",
callback_name,
key.surface_name,
e
);
}
}
}
}
pub(crate) fn with_selected<F>(&self, selector: &crate::Selector, mut f: F)
where
F: FnMut(&str, &ComponentInstance),
{
let system = self.inner.borrow();
let (primary, active) = self.get_output_handles();
for (key, surface) in system.app_state().surfaces_with_keys() {
let surface_info = crate::SurfaceInfo {
name: key.surface_name.clone(),
output: key.output_handle,
};
let output_info = system.app_state().get_output_info(key.output_handle);
if selector.matches(&surface_info, output_info, primary, active) {
f(&key.surface_name, surface.component_instance());
}
}
}
pub(crate) fn configure_selected<F>(&self, selector: &crate::Selector, mut f: F)
where
F: FnMut(&ComponentInstance, LayerSurfaceHandle<'_>),
{
let system = self.inner.borrow();
let (primary, active) = self.get_output_handles();
for (key, surface) in system.app_state().surfaces_with_keys() {
let surface_info = crate::SurfaceInfo {
name: key.surface_name.clone(),
output: key.output_handle,
};
let output_info = system.app_state().get_output_info(key.output_handle);
if selector.matches(&surface_info, output_info, primary, active) {
let surface_handle = LayerSurfaceHandle::from_window_state(surface);
f(surface.component_instance(), surface_handle);
}
}
}
pub(crate) fn count_selected(&self, selector: &crate::Selector) -> usize {
let system = self.inner.borrow();
let (primary, active) = self.get_output_handles();
system
.app_state()
.surfaces_with_keys()
.filter(|(key, _)| {
let surface_info = crate::SurfaceInfo {
name: key.surface_name.clone(),
output: key.output_handle,
};
let output_info = system.app_state().get_output_info(key.output_handle);
selector.matches(&surface_info, output_info, primary, active)
})
.count()
}
pub(crate) fn get_selected_info(&self, selector: &crate::Selector) -> Vec<crate::SurfaceInfo> {
let system = self.inner.borrow();
let (primary, active) = self.get_output_handles();
system
.app_state()
.surfaces_with_keys()
.filter_map(|(key, _)| {
let surface_info = crate::SurfaceInfo {
name: key.surface_name.clone(),
output: key.output_handle,
};
let output_info = system.app_state().get_output_info(key.output_handle);
if selector.matches(&surface_info, output_info, primary, active) {
Some(surface_info)
} else {
None
}
})
.collect()
}
}
impl ShellRuntime for Shell {

View file

@ -19,10 +19,12 @@ fn main() -> Result<()> {
log::info!("Shell has surfaces: {:?}", shell.surface_names());
log::info!("Has StatusBar surface: {}", shell.has_surface("StatusBar"));
shell.on("StatusBar", "settings-clicked", |_control| {
shell
.select(Surface::named("StatusBar"))
.on_callback("settings-clicked", |_control| {
log::info!("Settings button clicked");
Value::Void
})?;
});
log::info!("Registered callback for settings-clicked");

View file

@ -24,17 +24,21 @@ fn main() -> Result<()> {
.namespace("multi-surface-dock")
.build()?;
shell.on("TopBar", "workspace_clicked", |_control| {
shell
.select(Surface::named("TopBar"))
.on_callback("workspace_clicked", |_control| {
log::info!("Workspace button clicked in TopBar");
Value::Void
})?;
});
shell.on_with_args("Dock", "app_clicked", |args, _control| {
shell
.select(Surface::named("Dock"))
.on_callback_with_args("app_clicked", |args, _control| {
if let Some(Value::String(app_name)) = args.first() {
log::info!("App clicked in Dock: {}", app_name.as_str());
}
Value::Void
})?;
});
log::info!("Running shell with surfaces: {:?}", shell.surface_names());

View file

@ -77,10 +77,12 @@ fn setup_toggle_size_callback(
sender: &Rc<Sender<UiUpdate>>,
shell: &Shell,
state: &Rc<RefCell<BarState>>,
) -> Result<()> {
) {
let state_clone = Rc::clone(state);
let sender_clone = Rc::clone(sender);
shell.on("Bar", "toggle-size", move |control| {
shell
.select(Surface::named("Bar"))
.on_callback("toggle-size", move |control| {
let is_expanded = {
let mut st = state_clone.borrow_mut();
st.is_expanded = !st.is_expanded;
@ -121,17 +123,19 @@ fn setup_toggle_size_callback(
}
Value::Struct(Struct::from_iter([("expanded".into(), is_expanded.into())]))
})
});
}
fn setup_anchor_switch_callback(
sender: &Rc<Sender<UiUpdate>>,
shell: &Shell,
state: &Rc<RefCell<BarState>>,
) -> Result<()> {
) {
let state_clone = Rc::clone(state);
let sender_clone = Rc::clone(sender);
shell.on("Bar", "switch-anchor", move |control| {
shell
.select(Surface::named("Bar"))
.on_callback("switch-anchor", move |control| {
let anchor_name = {
let mut st = state_clone.borrow_mut();
st.next_anchor();
@ -156,17 +160,19 @@ fn setup_anchor_switch_callback(
"anchor".into(),
SharedString::from(anchor_name).into(),
)]))
})
});
}
fn setup_layer_switch_callback(
sender: &Rc<Sender<UiUpdate>>,
shell: &Shell,
state: &Rc<RefCell<BarState>>,
) -> Result<()> {
) {
let state_clone = Rc::clone(state);
let sender_clone = Rc::clone(sender);
shell.on("Bar", "switch-layer", move |control| {
shell
.select(Surface::named("Bar"))
.on_callback("switch-layer", move |control| {
let layer_name = {
let mut st = state_clone.borrow_mut();
let new_layer = st.next_layer();
@ -191,7 +197,7 @@ fn setup_layer_switch_callback(
"layer".into(),
SharedString::from(layer_name).into(),
)]))
})
});
}
fn main() -> Result<()> {
@ -214,7 +220,7 @@ fn main() -> Result<()> {
.namespace("runtime-control-example")
.build()?;
shell.with_all_surfaces(|_name, component| {
shell.select(Surface::all()).with_component(|component| {
log::info!("Initializing properties for Bar surface");
let state_ref = state.borrow();
@ -270,9 +276,9 @@ fn main() -> Result<()> {
let sender_rc = Rc::new(sender);
setup_toggle_size_callback(&sender_rc, &shell, &state)?;
setup_anchor_switch_callback(&sender_rc, &shell, &state)?;
setup_layer_switch_callback(&sender_rc, &shell, &state)?;
setup_toggle_size_callback(&sender_rc, &shell, &state);
setup_anchor_switch_callback(&sender_rc, &shell, &state);
setup_layer_switch_callback(&sender_rc, &shell, &state);
shell.run()?;
Ok(())

View file

@ -121,9 +121,10 @@ pub mod window;
pub use layer_shika_composition::{Error, Handle, Result, SurfaceHandle};
pub use shell::{
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellRuntime,
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
CompiledUiSource, Output, Selection, Selector, Surface, SurfaceInfo, DEFAULT_COMPONENT_NAME,
DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell, ShellBuilder, ShellConfig, ShellControl,
ShellEventContext, ShellRuntime, ShellSurfaceConfigHandler, SurfaceComponentConfig,
SurfaceConfigBuilder, SurfaceDefinition,
};
pub use window::{

View file

@ -9,9 +9,10 @@
#![allow(clippy::pub_use)]
pub use crate::shell::{
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellRuntime,
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
CompiledUiSource, Output, Selection, Selector, Surface, SurfaceInfo, DEFAULT_COMPONENT_NAME,
DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell, ShellBuilder, ShellConfig, ShellControl,
ShellEventContext, ShellRuntime, ShellSurfaceConfigHandler, SurfaceComponentConfig,
SurfaceConfigBuilder, SurfaceDefinition,
};
pub use crate::window::{

View file

@ -1,5 +1,6 @@
pub use layer_shika_composition::{
CompiledUiSource, DEFAULT_COMPONENT_NAME, DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell,
ShellBuilder, ShellConfig, ShellControl, ShellEventContext, ShellRuntime,
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
CompiledUiSource, Output, Selection, Selector, Surface, SurfaceInfo, DEFAULT_COMPONENT_NAME,
DEFAULT_SURFACE_NAME, LayerSurfaceHandle, Shell, ShellBuilder, ShellConfig, ShellControl,
ShellEventContext, ShellRuntime, ShellSurfaceConfigHandler, SurfaceComponentConfig,
SurfaceConfigBuilder, SurfaceDefinition,
};