mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-12-12 13:25:54 +00:00
feat: add surface command for shell control
This commit is contained in:
parent
0aa0aeae0b
commit
c2064c6012
6 changed files with 480 additions and 36 deletions
|
|
@ -376,6 +376,16 @@ impl AppState {
|
|||
.map(|(_, v)| v)
|
||||
}
|
||||
|
||||
pub fn surfaces_by_name_mut(
|
||||
&mut self,
|
||||
surface_name: &str,
|
||||
) -> impl Iterator<Item = &mut PerOutputSurface> {
|
||||
self.surfaces
|
||||
.iter_mut()
|
||||
.filter(move |(k, _)| k.surface_name == surface_name)
|
||||
.map(|(_, v)| v)
|
||||
}
|
||||
|
||||
pub fn get_output_by_handle(&self, handle: OutputHandle) -> Option<&PerOutputSurface> {
|
||||
self.get_first_surface_for_output(handle)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,42 @@ impl SurfaceState {
|
|||
self.rendering.update_size(width, height, scale_factor);
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
pub fn update_size_with_compositor_logic(
|
||||
&mut self,
|
||||
requested_width: u32,
|
||||
requested_height: u32,
|
||||
) {
|
||||
let scale_factor = self.event_context.borrow().scale_factor();
|
||||
let output_width = self.output_size().width;
|
||||
|
||||
let target_width = if requested_width == 0 || (requested_width == 1 && output_width > 1) {
|
||||
if scale_factor > 1.0 {
|
||||
(output_width as f32 / scale_factor).round() as u32
|
||||
} else {
|
||||
output_width
|
||||
}
|
||||
} else {
|
||||
requested_width
|
||||
};
|
||||
|
||||
let target_height = if requested_height > 0 {
|
||||
requested_height
|
||||
} else {
|
||||
let h = self.height();
|
||||
if scale_factor > 1.0 {
|
||||
(h as f32 / scale_factor).round() as u32
|
||||
} else {
|
||||
h
|
||||
}
|
||||
};
|
||||
|
||||
self.rendering
|
||||
.update_size(target_width, target_height, scale_factor);
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) {
|
||||
self.event_context
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use layer_shika_adapters::SurfaceState;
|
||||
use layer_shika_adapters::platform::slint_interpreter::ComponentInstance;
|
||||
use layer_shika_adapters::platform::wayland::{Anchor, WaylandKeyboardInteractivity, WaylandLayer};
|
||||
use layer_shika_domain::value_objects::anchor::AnchorEdges;
|
||||
use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
||||
use layer_shika_domain::value_objects::layer::Layer;
|
||||
use layer_shika_domain::value_objects::margins::Margins;
|
||||
|
|
@ -18,6 +19,30 @@ impl<'a> LayerSurfaceHandle<'a> {
|
|||
self.window_state.layer_surface().set_anchor(anchor);
|
||||
}
|
||||
|
||||
pub fn set_anchor_edges(&self, anchor: AnchorEdges) {
|
||||
let wayland_anchor = Self::convert_anchor(anchor);
|
||||
self.window_state.layer_surface().set_anchor(wayland_anchor);
|
||||
}
|
||||
|
||||
fn convert_anchor(anchor: AnchorEdges) -> Anchor {
|
||||
let mut result = Anchor::empty();
|
||||
|
||||
if anchor.has_top() {
|
||||
result = result.union(Anchor::Top);
|
||||
}
|
||||
if anchor.has_bottom() {
|
||||
result = result.union(Anchor::Bottom);
|
||||
}
|
||||
if anchor.has_left() {
|
||||
result = result.union(Anchor::Left);
|
||||
}
|
||||
if anchor.has_right() {
|
||||
result = result.union(Anchor::Right);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn set_size(&self, width: u32, height: u32) {
|
||||
self.window_state.layer_surface().set_size(width, height);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ pub use layer_shika_domain::value_objects::popup_request::{
|
|||
pub use layer_surface::{LayerSurfaceHandle, ShellSurfaceConfigHandler};
|
||||
pub use popup_builder::PopupBuilder;
|
||||
pub use shell_runtime::{DEFAULT_SURFACE_NAME, ShellRuntime};
|
||||
pub use system::{EventDispatchContext, ShellControl};
|
||||
pub use system::{EventDispatchContext, ShellControl, SurfaceControlHandle};
|
||||
pub use value_conversion::IntoValue;
|
||||
|
||||
pub use shell::{
|
||||
|
|
@ -70,8 +70,9 @@ pub mod prelude {
|
|||
OutputPolicy, OutputRegistry, PopupBuilder, PopupHandle, PopupPlacement,
|
||||
PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, Shell, ShellBuilder,
|
||||
ShellConfig, ShellControl, ShellEventContext, ShellEventLoop, ShellRuntime,
|
||||
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder, SurfaceDefinition,
|
||||
SurfaceEntry, SurfaceHandle, SurfaceMetadata, SurfaceRegistry,
|
||||
ShellSurfaceConfigHandler, SurfaceComponentConfig, SurfaceConfigBuilder,
|
||||
SurfaceControlHandle, SurfaceDefinition, SurfaceEntry, SurfaceHandle, SurfaceMetadata,
|
||||
SurfaceRegistry,
|
||||
};
|
||||
|
||||
pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ 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::system::{
|
||||
EventDispatchContext, PopupCommand, ShellCommand, ShellControl, SurfaceCommand,
|
||||
};
|
||||
use crate::value_conversion::IntoValue;
|
||||
use crate::{Error, Result};
|
||||
use layer_shika_adapters::errors::EventLoopError;
|
||||
|
|
@ -220,7 +222,7 @@ pub struct Shell {
|
|||
inner: Rc<RefCell<dyn WaylandSystemOps>>,
|
||||
registry: SurfaceRegistry,
|
||||
compilation_result: Rc<CompilationResult>,
|
||||
popup_command_sender: channel::Sender<PopupCommand>,
|
||||
command_sender: channel::Sender<ShellCommand>,
|
||||
output_connected_handlers: Rc<RefCell<Vec<OutputConnectedHandler>>>,
|
||||
output_disconnected_handlers: Rc<RefCell<Vec<OutputDisconnectedHandler>>>,
|
||||
}
|
||||
|
|
@ -403,12 +405,12 @@ impl Shell {
|
|||
inner: Rc::clone(&inner_rc),
|
||||
registry,
|
||||
compilation_result,
|
||||
popup_command_sender: sender,
|
||||
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_command_handler(receiver)?;
|
||||
|
||||
log::info!("Shell created (single-window mode)");
|
||||
|
||||
|
|
@ -463,12 +465,12 @@ impl Shell {
|
|||
inner: Rc::clone(&inner_rc),
|
||||
registry,
|
||||
compilation_result,
|
||||
popup_command_sender: sender,
|
||||
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_command_handler(receiver)?;
|
||||
|
||||
log::info!(
|
||||
"Shell created (multi-surface mode) with surfaces: {:?}",
|
||||
|
|
@ -478,7 +480,7 @@ impl Shell {
|
|||
Ok(shell)
|
||||
}
|
||||
|
||||
fn setup_popup_command_handler(&self, receiver: channel::Channel<PopupCommand>) -> Result<()> {
|
||||
fn setup_command_handler(&self, receiver: channel::Channel<ShellCommand>) -> Result<()> {
|
||||
let loop_handle = self.inner.borrow().event_loop_handle();
|
||||
let control = self.control();
|
||||
|
||||
|
|
@ -488,23 +490,15 @@ impl Shell {
|
|||
let mut ctx = crate::system::EventDispatchContext::from_app_state(app_state);
|
||||
|
||||
match command {
|
||||
PopupCommand::Show(request) => {
|
||||
if let Err(e) = ctx.show_popup(&request, Some(control.clone())) {
|
||||
log::error!("Failed to show popup: {}", e);
|
||||
}
|
||||
ShellCommand::Popup(popup_cmd) => {
|
||||
Self::handle_popup_command(popup_cmd, &mut ctx, &control);
|
||||
}
|
||||
PopupCommand::Close(handle) => {
|
||||
if let Err(e) = ctx.close_popup(handle) {
|
||||
log::error!("Failed to close popup: {}", e);
|
||||
}
|
||||
ShellCommand::Surface(surface_cmd) => {
|
||||
Self::handle_surface_command(surface_cmd, &mut ctx);
|
||||
}
|
||||
PopupCommand::Resize {
|
||||
handle,
|
||||
width,
|
||||
height,
|
||||
} => {
|
||||
if let Err(e) = ctx.resize_popup(handle, width, height) {
|
||||
log::error!("Failed to resize popup: {}", e);
|
||||
ShellCommand::Render => {
|
||||
if let Err(e) = ctx.render_frame_if_dirty() {
|
||||
log::error!("Failed to render frame: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -513,7 +507,7 @@ impl Shell {
|
|||
.map_err(|e| {
|
||||
Error::Adapter(
|
||||
EventLoopError::InsertSource {
|
||||
message: format!("Failed to setup popup command handler: {e:?}"),
|
||||
message: format!("Failed to setup command handler: {e:?}"),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
|
|
@ -522,9 +516,134 @@ impl Shell {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_popup_command(
|
||||
command: PopupCommand,
|
||||
ctx: &mut EventDispatchContext<'_>,
|
||||
control: &ShellControl,
|
||||
) {
|
||||
match command {
|
||||
PopupCommand::Show(request) => {
|
||||
if let Err(e) = ctx.show_popup(&request, Some(control.clone())) {
|
||||
log::error!("Failed to show popup: {}", e);
|
||||
}
|
||||
}
|
||||
PopupCommand::Close(handle) => {
|
||||
if let Err(e) = ctx.close_popup(handle) {
|
||||
log::error!("Failed to close popup: {}", e);
|
||||
}
|
||||
}
|
||||
PopupCommand::Resize {
|
||||
handle,
|
||||
width,
|
||||
height,
|
||||
} => {
|
||||
if let Err(e) = ctx.resize_popup(handle, width, height) {
|
||||
log::error!("Failed to resize popup: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_surface_command(command: SurfaceCommand, ctx: &mut EventDispatchContext<'_>) {
|
||||
match command {
|
||||
SurfaceCommand::Resize {
|
||||
name,
|
||||
width,
|
||||
height,
|
||||
} => {
|
||||
log::debug!("Surface command: Resize '{}' to {}x{}", name, width, height);
|
||||
for surface in ctx.surfaces_by_name_mut(&name) {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
handle.set_size(width, height);
|
||||
handle.commit();
|
||||
|
||||
surface.update_size_with_compositor_logic(width, height);
|
||||
}
|
||||
}
|
||||
SurfaceCommand::SetAnchor { name, anchor } => {
|
||||
log::debug!("Surface command: SetAnchor '{}' to {:?}", name, anchor);
|
||||
for surface in ctx.surfaces_by_name(&name) {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
handle.set_anchor_edges(anchor);
|
||||
handle.commit();
|
||||
}
|
||||
}
|
||||
SurfaceCommand::SetExclusiveZone { name, zone } => {
|
||||
log::debug!("Surface command: SetExclusiveZone '{}' to {}", name, zone);
|
||||
for surface in ctx.surfaces_by_name(&name) {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
handle.set_exclusive_zone(zone);
|
||||
handle.commit();
|
||||
}
|
||||
}
|
||||
SurfaceCommand::SetMargins { name, margins } => {
|
||||
log::debug!("Surface command: SetMargins '{}' to {:?}", name, margins);
|
||||
for surface in ctx.surfaces_by_name(&name) {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
handle.set_margins(margins);
|
||||
handle.commit();
|
||||
}
|
||||
}
|
||||
SurfaceCommand::SetLayer { name, layer } => {
|
||||
log::debug!("Surface command: SetLayer '{}' to {:?}", name, layer);
|
||||
for surface in ctx.surfaces_by_name(&name) {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
handle.set_layer(layer);
|
||||
handle.commit();
|
||||
}
|
||||
}
|
||||
SurfaceCommand::SetKeyboardInteractivity { name, mode } => {
|
||||
log::debug!(
|
||||
"Surface command: SetKeyboardInteractivity '{}' to {:?}",
|
||||
name,
|
||||
mode
|
||||
);
|
||||
for surface in ctx.surfaces_by_name(&name) {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
handle.set_keyboard_interactivity(mode);
|
||||
handle.commit();
|
||||
}
|
||||
}
|
||||
SurfaceCommand::SetOutputPolicy { name, policy } => {
|
||||
log::debug!(
|
||||
"Surface command: SetOutputPolicy '{}' to {:?}",
|
||||
name,
|
||||
policy
|
||||
);
|
||||
log::warn!(
|
||||
"SetOutputPolicy is not yet implemented - requires runtime surface spawning"
|
||||
);
|
||||
}
|
||||
SurfaceCommand::SetScaleFactor { name, factor } => {
|
||||
log::debug!("Surface command: SetScaleFactor '{}' to {:?}", name, factor);
|
||||
log::warn!(
|
||||
"SetScaleFactor is not yet implemented - requires runtime surface property updates"
|
||||
);
|
||||
}
|
||||
SurfaceCommand::ApplyConfig { name, config } => {
|
||||
log::debug!("Surface command: ApplyConfig '{}'", name);
|
||||
for surface in ctx.surfaces_by_name(&name) {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
|
||||
handle.set_size(config.dimensions.width(), config.dimensions.height());
|
||||
handle.set_anchor_edges(config.anchor);
|
||||
handle.set_exclusive_zone(config.exclusive_zone);
|
||||
handle.set_margins(config.margin);
|
||||
handle.set_layer(config.layer);
|
||||
handle.set_keyboard_interactivity(config.keyboard_interactivity);
|
||||
handle.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = ctx.render_frame_if_dirty() {
|
||||
log::error!("Failed to render frame after surface command: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn control(&self) -> ShellControl {
|
||||
ShellControl::new(self.popup_command_sender.clone())
|
||||
ShellControl::new(self.command_sender.clone())
|
||||
}
|
||||
|
||||
pub fn surface_names(&self) -> Vec<&str> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::event_loop::FromAppState;
|
||||
use crate::layer_surface::LayerSurfaceHandle;
|
||||
use crate::{Error, Result};
|
||||
use layer_shika_adapters::platform::calloop::channel;
|
||||
use layer_shika_adapters::platform::slint::ComponentHandle;
|
||||
|
|
@ -6,8 +7,12 @@ use layer_shika_adapters::platform::slint_interpreter::{
|
|||
CompilationResult, ComponentDefinition, ComponentInstance, Value,
|
||||
};
|
||||
use layer_shika_adapters::{AppState, PopupManager, SurfaceState};
|
||||
use layer_shika_domain::config::SurfaceConfig;
|
||||
use layer_shika_domain::entities::output_registry::OutputRegistry;
|
||||
use layer_shika_domain::errors::DomainError;
|
||||
use layer_shika_domain::prelude::{
|
||||
AnchorEdges, KeyboardInteractivity, Layer, Margins, OutputPolicy, ScaleFactor,
|
||||
};
|
||||
use layer_shika_domain::value_objects::dimensions::PopupDimensions;
|
||||
use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
||||
use layer_shika_domain::value_objects::output_info::OutputInfo;
|
||||
|
|
@ -28,19 +33,65 @@ pub enum PopupCommand {
|
|||
},
|
||||
}
|
||||
|
||||
pub enum SurfaceCommand {
|
||||
Resize {
|
||||
name: String,
|
||||
width: u32,
|
||||
height: u32,
|
||||
},
|
||||
SetAnchor {
|
||||
name: String,
|
||||
anchor: AnchorEdges,
|
||||
},
|
||||
SetExclusiveZone {
|
||||
name: String,
|
||||
zone: i32,
|
||||
},
|
||||
SetMargins {
|
||||
name: String,
|
||||
margins: Margins,
|
||||
},
|
||||
SetLayer {
|
||||
name: String,
|
||||
layer: Layer,
|
||||
},
|
||||
SetOutputPolicy {
|
||||
name: String,
|
||||
policy: OutputPolicy,
|
||||
},
|
||||
SetScaleFactor {
|
||||
name: String,
|
||||
factor: ScaleFactor,
|
||||
},
|
||||
SetKeyboardInteractivity {
|
||||
name: String,
|
||||
mode: KeyboardInteractivity,
|
||||
},
|
||||
ApplyConfig {
|
||||
name: String,
|
||||
config: SurfaceConfig,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum ShellCommand {
|
||||
Popup(PopupCommand),
|
||||
Surface(SurfaceCommand),
|
||||
Render,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ShellControl {
|
||||
sender: channel::Sender<PopupCommand>,
|
||||
sender: channel::Sender<ShellCommand>,
|
||||
}
|
||||
|
||||
impl ShellControl {
|
||||
pub fn new(sender: channel::Sender<PopupCommand>) -> Self {
|
||||
pub fn new(sender: channel::Sender<ShellCommand>) -> Self {
|
||||
Self { sender }
|
||||
}
|
||||
|
||||
pub fn show_popup(&self, request: &PopupRequest) -> Result<()> {
|
||||
self.sender
|
||||
.send(PopupCommand::Show(request.clone()))
|
||||
.send(ShellCommand::Popup(PopupCommand::Show(request.clone())))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send popup show command: channel closed".to_string(),
|
||||
|
|
@ -76,26 +127,186 @@ impl ShellControl {
|
|||
}
|
||||
|
||||
pub fn close_popup(&self, handle: PopupHandle) -> Result<()> {
|
||||
self.sender.send(PopupCommand::Close(handle)).map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send popup close command: channel closed".to_string(),
|
||||
self.sender
|
||||
.send(ShellCommand::Popup(PopupCommand::Close(handle)))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send popup close command: channel closed".to_string(),
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resize_popup(&self, handle: PopupHandle, width: f32, height: f32) -> Result<()> {
|
||||
self.sender
|
||||
.send(PopupCommand::Resize {
|
||||
.send(ShellCommand::Popup(PopupCommand::Resize {
|
||||
handle,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send popup resize command: channel closed".to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn request_redraw(&self) -> Result<()> {
|
||||
self.sender.send(ShellCommand::Render).map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send redraw command: channel closed".to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn surface(&self, name: impl Into<String>) -> SurfaceControlHandle {
|
||||
SurfaceControlHandle {
|
||||
name: name.into(),
|
||||
sender: self.sender.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SurfaceControlHandle {
|
||||
name: String,
|
||||
sender: channel::Sender<ShellCommand>,
|
||||
}
|
||||
|
||||
impl SurfaceControlHandle {
|
||||
pub fn resize(&self, width: u32, height: u32) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::Resize {
|
||||
name: self.name.clone(),
|
||||
width,
|
||||
height,
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface resize command: channel closed".to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_width(&self, width: u32) -> Result<()> {
|
||||
self.resize(width, 0)
|
||||
}
|
||||
|
||||
pub fn set_height(&self, height: u32) -> Result<()> {
|
||||
self.resize(0, height)
|
||||
}
|
||||
|
||||
pub fn set_anchor(&self, anchor: AnchorEdges) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::SetAnchor {
|
||||
name: self.name.clone(),
|
||||
anchor,
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface set_anchor command: channel closed"
|
||||
.to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_exclusive_zone(&self, zone: i32) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::SetExclusiveZone {
|
||||
name: self.name.clone(),
|
||||
zone,
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface set_exclusive_zone command: channel closed"
|
||||
.to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_margins(&self, margins: impl Into<Margins>) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::SetMargins {
|
||||
name: self.name.clone(),
|
||||
margins: margins.into(),
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface set_margins command: channel closed"
|
||||
.to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_layer(&self, layer: Layer) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::SetLayer {
|
||||
name: self.name.clone(),
|
||||
layer,
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface set_layer command: channel closed".to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_output_policy(&self, policy: OutputPolicy) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::SetOutputPolicy {
|
||||
name: self.name.clone(),
|
||||
policy,
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface set_output_policy command: channel closed"
|
||||
.to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_scale_factor(&self, factor: ScaleFactor) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::SetScaleFactor {
|
||||
name: self.name.clone(),
|
||||
factor,
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface set_scale_factor command: channel closed"
|
||||
.to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_keyboard_interactivity(&self, mode: KeyboardInteractivity) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(
|
||||
SurfaceCommand::SetKeyboardInteractivity {
|
||||
name: self.name.clone(),
|
||||
mode,
|
||||
},
|
||||
))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message:
|
||||
"Failed to send surface set_keyboard_interactivity command: channel closed"
|
||||
.to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn apply_config(&self, config: SurfaceConfig) -> Result<()> {
|
||||
self.sender
|
||||
.send(ShellCommand::Surface(SurfaceCommand::ApplyConfig {
|
||||
name: self.name.clone(),
|
||||
config,
|
||||
}))
|
||||
.map_err(|_| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: "Failed to send surface apply_config command: channel closed"
|
||||
.to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventDispatchContext<'a> {
|
||||
|
|
@ -121,6 +332,17 @@ fn extract_dimensions_from_callback(args: &[Value]) -> PopupDimensions {
|
|||
}
|
||||
|
||||
impl EventDispatchContext<'_> {
|
||||
pub(crate) fn surfaces_by_name(&self, name: &str) -> impl Iterator<Item = &SurfaceState> {
|
||||
self.app_state.surfaces_by_name(name)
|
||||
}
|
||||
|
||||
pub(crate) fn surfaces_by_name_mut(
|
||||
&mut self,
|
||||
name: &str,
|
||||
) -> impl Iterator<Item = &mut SurfaceState> {
|
||||
self.app_state.surfaces_by_name_mut(name)
|
||||
}
|
||||
|
||||
pub fn with_surface<F, R>(&self, name: &str, f: F) -> Result<R>
|
||||
where
|
||||
F: FnOnce(&ComponentInstance) -> R,
|
||||
|
|
@ -572,4 +794,35 @@ impl EventDispatchContext<'_> {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn configure_surface<F>(&mut self, name: &str, f: F) -> Result<()>
|
||||
where
|
||||
F: FnOnce(&ComponentInstance, LayerSurfaceHandle<'_>),
|
||||
{
|
||||
let surface = self
|
||||
.app_state
|
||||
.surfaces_by_name(name)
|
||||
.next()
|
||||
.ok_or_else(|| {
|
||||
Error::Domain(DomainError::Configuration {
|
||||
message: format!("Surface '{}' not found", name),
|
||||
})
|
||||
})?;
|
||||
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
let component = surface.component_instance();
|
||||
f(component, handle);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn configure_all_surfaces<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&ComponentInstance, LayerSurfaceHandle<'_>),
|
||||
{
|
||||
for surface in self.app_state.all_outputs() {
|
||||
let handle = LayerSurfaceHandle::from_window_state(surface);
|
||||
let component = surface.component_instance();
|
||||
f(component, handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue