mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-12-12 13:25:54 +00:00
refactor: migrate to selector system for surface and output
This commit is contained in:
parent
0d5a350f53
commit
dc950833ea
10 changed files with 589 additions and 275 deletions
|
|
@ -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};
|
||||
|
|
|
|||
96
crates/composition/src/selection.rs
Normal file
96
crates/composition/src/selection.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
180
crates/composition/src/selector.rs
Normal file
180
crates/composition/src/selector.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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| {
|
||||
log::info!("Settings button clicked");
|
||||
Value::Void
|
||||
})?;
|
||||
shell
|
||||
.select(Surface::named("StatusBar"))
|
||||
.on_callback("settings-clicked", |_control| {
|
||||
log::info!("Settings button clicked");
|
||||
Value::Void
|
||||
});
|
||||
|
||||
log::info!("Registered callback for settings-clicked");
|
||||
|
||||
|
|
|
|||
|
|
@ -24,17 +24,21 @@ fn main() -> Result<()> {
|
|||
.namespace("multi-surface-dock")
|
||||
.build()?;
|
||||
|
||||
shell.on("TopBar", "workspace_clicked", |_control| {
|
||||
log::info!("Workspace button clicked in TopBar");
|
||||
Value::Void
|
||||
})?;
|
||||
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| {
|
||||
if let Some(Value::String(app_name)) = args.first() {
|
||||
log::info!("App clicked in Dock: {}", app_name.as_str());
|
||||
}
|
||||
Value::Void
|
||||
})?;
|
||||
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());
|
||||
|
||||
|
|
|
|||
|
|
@ -77,121 +77,127 @@ 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| {
|
||||
let is_expanded = {
|
||||
let mut st = state_clone.borrow_mut();
|
||||
st.is_expanded = !st.is_expanded;
|
||||
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;
|
||||
|
||||
let new_size = if st.is_expanded { 64 } else { 32 };
|
||||
let new_size = if st.is_expanded { 64 } else { 32 };
|
||||
|
||||
let (width, height) = match st.current_anchor {
|
||||
AnchorPosition::Top | AnchorPosition::Bottom => {
|
||||
log::info!("Resizing horizontal bar to {}px", new_size);
|
||||
(0, new_size)
|
||||
let (width, height) = match st.current_anchor {
|
||||
AnchorPosition::Top | AnchorPosition::Bottom => {
|
||||
log::info!("Resizing horizontal bar to {}px", new_size);
|
||||
(0, new_size)
|
||||
}
|
||||
};
|
||||
|
||||
let bar = control.surface("Bar");
|
||||
if let Err(e) = bar.resize(width, height) {
|
||||
log::error!("Failed to resize bar: {}", e);
|
||||
}
|
||||
|
||||
if let Err(e) = bar.set_exclusive_zone(new_size.try_into().unwrap_or(32)) {
|
||||
log::error!("Failed to set exclusive zone: {}", e);
|
||||
}
|
||||
|
||||
if let Err(e) = control.surface("Bar").set_margins((0, 0, 0, 0)) {
|
||||
log::error!("Failed to set margins: {}", e);
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"Updated bar state: size={}, is_expanded={}",
|
||||
new_size,
|
||||
st.is_expanded
|
||||
);
|
||||
|
||||
st.is_expanded
|
||||
};
|
||||
|
||||
let bar = control.surface("Bar");
|
||||
if let Err(e) = bar.resize(width, height) {
|
||||
log::error!("Failed to resize bar: {}", e);
|
||||
if let Err(e) = sender_clone.send(UiUpdate::IsExpanded(is_expanded)) {
|
||||
log::error!("Failed to send UI update: {}", e);
|
||||
}
|
||||
|
||||
if let Err(e) = bar.set_exclusive_zone(new_size.try_into().unwrap_or(32)) {
|
||||
log::error!("Failed to set exclusive zone: {}", e);
|
||||
}
|
||||
|
||||
if let Err(e) = control.surface("Bar").set_margins((0, 0, 0, 0)) {
|
||||
log::error!("Failed to set margins: {}", e);
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"Updated bar state: size={}, is_expanded={}",
|
||||
new_size,
|
||||
st.is_expanded
|
||||
);
|
||||
|
||||
st.is_expanded
|
||||
};
|
||||
|
||||
if let Err(e) = sender_clone.send(UiUpdate::IsExpanded(is_expanded)) {
|
||||
log::error!("Failed to send UI update: {}", e);
|
||||
}
|
||||
|
||||
Value::Struct(Struct::from_iter([("expanded".into(), is_expanded.into())]))
|
||||
})
|
||||
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| {
|
||||
let anchor_name = {
|
||||
let mut st = state_clone.borrow_mut();
|
||||
st.next_anchor();
|
||||
shell
|
||||
.select(Surface::named("Bar"))
|
||||
.on_callback("switch-anchor", move |control| {
|
||||
let anchor_name = {
|
||||
let mut st = state_clone.borrow_mut();
|
||||
st.next_anchor();
|
||||
|
||||
log::info!("Switching to anchor: {}", st.anchor_name());
|
||||
log::info!("Switching to anchor: {}", st.anchor_name());
|
||||
|
||||
let bar = control.surface("Bar");
|
||||
if let Err(e) = bar.set_anchor(st.get_anchor_edges()) {
|
||||
log::error!("Failed to apply config: {}", e);
|
||||
let bar = control.surface("Bar");
|
||||
if let Err(e) = bar.set_anchor(st.get_anchor_edges()) {
|
||||
log::error!("Failed to apply config: {}", e);
|
||||
}
|
||||
|
||||
st.anchor_name()
|
||||
};
|
||||
|
||||
if let Err(e) = sender_clone.send(UiUpdate::CurrentAnchor(anchor_name.to_string())) {
|
||||
log::error!("Failed to send UI update: {}", e);
|
||||
}
|
||||
|
||||
st.anchor_name()
|
||||
};
|
||||
log::info!("Switched to {} anchor", anchor_name);
|
||||
|
||||
if let Err(e) = sender_clone.send(UiUpdate::CurrentAnchor(anchor_name.to_string())) {
|
||||
log::error!("Failed to send UI update: {}", e);
|
||||
}
|
||||
|
||||
log::info!("Switched to {} anchor", anchor_name);
|
||||
|
||||
Value::Struct(Struct::from_iter([(
|
||||
"anchor".into(),
|
||||
SharedString::from(anchor_name).into(),
|
||||
)]))
|
||||
})
|
||||
Value::Struct(Struct::from_iter([(
|
||||
"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| {
|
||||
let layer_name = {
|
||||
let mut st = state_clone.borrow_mut();
|
||||
let new_layer = st.next_layer();
|
||||
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();
|
||||
|
||||
log::info!("Switching to layer: {:?}", new_layer);
|
||||
log::info!("Switching to layer: {:?}", new_layer);
|
||||
|
||||
let bar = control.surface("Bar");
|
||||
if let Err(e) = bar.set_layer(new_layer) {
|
||||
log::error!("Failed to set layer: {}", e);
|
||||
let bar = control.surface("Bar");
|
||||
if let Err(e) = bar.set_layer(new_layer) {
|
||||
log::error!("Failed to set layer: {}", e);
|
||||
}
|
||||
|
||||
st.layer_name()
|
||||
};
|
||||
|
||||
if let Err(e) = sender_clone.send(UiUpdate::CurrentLayer(layer_name.to_string())) {
|
||||
log::error!("Failed to send UI update: {}", e);
|
||||
}
|
||||
|
||||
st.layer_name()
|
||||
};
|
||||
log::info!("Switched to {} layer", layer_name);
|
||||
|
||||
if let Err(e) = sender_clone.send(UiUpdate::CurrentLayer(layer_name.to_string())) {
|
||||
log::error!("Failed to send UI update: {}", e);
|
||||
}
|
||||
|
||||
log::info!("Switched to {} layer", layer_name);
|
||||
|
||||
Value::Struct(Struct::from_iter([(
|
||||
"layer".into(),
|
||||
SharedString::from(layer_name).into(),
|
||||
)]))
|
||||
})
|
||||
Value::Struct(Struct::from_iter([(
|
||||
"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(())
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue