mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2026-01-22 07:05:56 +00:00
refactor: minor lock callback refactor
This commit is contained in:
parent
6cbbce773f
commit
d5b4953c1a
3 changed files with 215 additions and 77 deletions
|
|
@ -4,7 +4,99 @@ use layer_shika_domain::value_objects::output_info::OutputInfo;
|
|||
use slint_interpreter::{ComponentInstance, Value};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type LockCallbackHandler = Rc<dyn Fn(&[Value]) -> Value>;
|
||||
pub(crate) trait FilterContext {
|
||||
fn matches_filter(&self, filter: &dyn Fn(&Self) -> bool) -> bool {
|
||||
filter(self)
|
||||
}
|
||||
}
|
||||
|
||||
type FilterFn<Ctx> = Box<dyn Fn(&Ctx) -> bool>;
|
||||
|
||||
pub(crate) struct CallbackEntry<Ctx: FilterContext, Handler> {
|
||||
name: String,
|
||||
handler: Handler,
|
||||
filter: Option<FilterFn<Ctx>>,
|
||||
}
|
||||
|
||||
impl<Ctx: FilterContext, Handler: Clone> CallbackEntry<Ctx, Handler> {
|
||||
fn new(name: impl Into<String>, handler: Handler) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
handler,
|
||||
filter: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_filter<F>(name: impl Into<String>, handler: Handler, filter: F) -> Self
|
||||
where
|
||||
F: Fn(&Ctx) -> bool + 'static,
|
||||
{
|
||||
Self {
|
||||
name: name.into(),
|
||||
handler,
|
||||
filter: Some(Box::new(filter)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn should_apply(&self, context: &Ctx) -> bool {
|
||||
self.filter
|
||||
.as_ref()
|
||||
.is_none_or(|f| context.matches_filter(f.as_ref()))
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn handler(&self) -> &Handler {
|
||||
&self.handler
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx: FilterContext, Handler: Clone> Clone for CallbackEntry<Ctx, Handler> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
name: self.name.clone(),
|
||||
handler: self.handler.clone(),
|
||||
filter: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type CallbackHandler = Rc<dyn Fn(&[Value]) -> Value>;
|
||||
|
||||
pub struct LockCallbackContext {
|
||||
pub component_name: String,
|
||||
pub output_handle: OutputHandle,
|
||||
pub output_info: Option<OutputInfo>,
|
||||
pub primary_handle: Option<OutputHandle>,
|
||||
pub active_handle: Option<OutputHandle>,
|
||||
}
|
||||
|
||||
impl LockCallbackContext {
|
||||
pub fn new(
|
||||
component_name: String,
|
||||
output_handle: OutputHandle,
|
||||
output_info: Option<OutputInfo>,
|
||||
primary_handle: Option<OutputHandle>,
|
||||
active_handle: Option<OutputHandle>,
|
||||
) -> Self {
|
||||
Self {
|
||||
component_name,
|
||||
output_handle,
|
||||
output_info,
|
||||
primary_handle,
|
||||
active_handle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterContext for LockCallbackContext {}
|
||||
|
||||
pub type LockCallbackEntry = CallbackEntry<LockCallbackContext, CallbackHandler>;
|
||||
|
||||
pub type LockCallback = LockCallbackEntry;
|
||||
|
||||
pub type OutputFilter = Rc<
|
||||
dyn Fn(
|
||||
&str,
|
||||
|
|
@ -15,66 +107,64 @@ pub type OutputFilter = Rc<
|
|||
) -> bool,
|
||||
>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LockCallback {
|
||||
name: String,
|
||||
handler: LockCallbackHandler,
|
||||
filter: Option<OutputFilter>,
|
||||
pub fn create_lock_callback(name: impl Into<String>, handler: CallbackHandler) -> LockCallback {
|
||||
LockCallbackEntry::new(name, handler)
|
||||
}
|
||||
|
||||
impl LockCallback {
|
||||
pub fn new(name: impl Into<String>, handler: LockCallbackHandler) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
handler,
|
||||
filter: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_filter(
|
||||
pub fn create_lock_callback_with_output_filter<F>(
|
||||
name: impl Into<String>,
|
||||
handler: LockCallbackHandler,
|
||||
filter: OutputFilter,
|
||||
) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
handler,
|
||||
filter: Some(filter),
|
||||
}
|
||||
}
|
||||
handler: CallbackHandler,
|
||||
output_filter: F,
|
||||
) -> LockCallback
|
||||
where
|
||||
F: Fn(
|
||||
&str,
|
||||
OutputHandle,
|
||||
Option<&OutputInfo>,
|
||||
Option<OutputHandle>,
|
||||
Option<OutputHandle>,
|
||||
) -> bool
|
||||
+ 'static,
|
||||
{
|
||||
LockCallbackEntry::with_filter(name, handler, move |ctx: &LockCallbackContext| {
|
||||
output_filter(
|
||||
&ctx.component_name,
|
||||
ctx.output_handle,
|
||||
ctx.output_info.as_ref(),
|
||||
ctx.primary_handle,
|
||||
ctx.active_handle,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn should_apply(
|
||||
pub trait LockCallbackExt {
|
||||
fn apply_to_component(&self, component: &ComponentInstance) -> Result<()>;
|
||||
fn apply_with_context(
|
||||
&self,
|
||||
component_name: &str,
|
||||
output_handle: OutputHandle,
|
||||
output_info: Option<&OutputInfo>,
|
||||
primary_handle: Option<OutputHandle>,
|
||||
active_handle: Option<OutputHandle>,
|
||||
) -> bool {
|
||||
self.filter.as_ref().map_or_else(
|
||||
|| true,
|
||||
|f| {
|
||||
f(
|
||||
component_name,
|
||||
output_handle,
|
||||
output_info,
|
||||
primary_handle,
|
||||
active_handle,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
component: &ComponentInstance,
|
||||
context: &LockCallbackContext,
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
||||
pub fn apply_to(&self, component: &ComponentInstance) -> Result<()> {
|
||||
let handler = Rc::clone(&self.handler);
|
||||
impl LockCallbackExt for LockCallbackEntry {
|
||||
fn apply_to_component(&self, component: &ComponentInstance) -> Result<()> {
|
||||
let handler = Rc::clone(self.handler());
|
||||
component
|
||||
.set_callback(&self.name, move |args| handler(args))
|
||||
.set_callback(self.name(), move |args| handler(args))
|
||||
.map_err(|e| LayerShikaError::InvalidInput {
|
||||
message: format!("Failed to register callback '{}': {e}", self.name),
|
||||
message: format!("Failed to register callback '{}': {e}", self.name()),
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn name(&self) -> &String {
|
||||
&self.name
|
||||
fn apply_with_context(
|
||||
&self,
|
||||
component: &ComponentInstance,
|
||||
context: &LockCallbackContext,
|
||||
) -> Result<()> {
|
||||
if !self.should_apply(context) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.apply_to_component(component)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use super::callbacks::{LockCallbackContext, LockCallbackExt};
|
||||
use crate::errors::Result;
|
||||
use crate::rendering::femtovg::main_window::FemtoVGWindow;
|
||||
use crate::rendering::femtovg::renderable_window::RenderableWindow;
|
||||
|
|
@ -51,6 +52,11 @@ pub struct ActiveLockSurface {
|
|||
component: Option<ComponentState>,
|
||||
scale_factor: f32,
|
||||
has_fractional_scale: bool,
|
||||
output_handle: Option<OutputHandle>,
|
||||
component_name: Option<String>,
|
||||
output_info: Option<OutputInfo>,
|
||||
primary_handle: Option<OutputHandle>,
|
||||
active_handle: Option<OutputHandle>,
|
||||
}
|
||||
|
||||
impl ActiveLockSurface {
|
||||
|
|
@ -61,6 +67,11 @@ impl ActiveLockSurface {
|
|||
window,
|
||||
component: None,
|
||||
scale_factor: 1.0,
|
||||
output_handle: None,
|
||||
component_name: None,
|
||||
output_info: None,
|
||||
primary_handle: None,
|
||||
active_handle: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +84,11 @@ impl ActiveLockSurface {
|
|||
) -> Result<()> {
|
||||
self.surface.handle_configure(serial, width, height);
|
||||
self.scale_factor = context.scale_factor;
|
||||
self.output_handle = Some(context.output_handle);
|
||||
self.component_name = Some(context.component_name.clone());
|
||||
self.output_info.clone_from(&context.output_info);
|
||||
self.primary_handle = context.primary_handle;
|
||||
self.active_handle = context.active_handle;
|
||||
let dimensions = match SurfaceDimensions::calculate(width, height, context.scale_factor) {
|
||||
Ok(dimensions) => dimensions,
|
||||
Err(err) => {
|
||||
|
|
@ -103,22 +119,25 @@ impl ActiveLockSurface {
|
|||
self.window
|
||||
.window()
|
||||
.dispatch_event(WindowEvent::WindowActiveChanged(true));
|
||||
for callback in &context.callbacks {
|
||||
if callback.should_apply(
|
||||
&context.component_name,
|
||||
|
||||
let callback_context = LockCallbackContext::new(
|
||||
context.component_name.clone(),
|
||||
context.output_handle,
|
||||
context.output_info.as_ref(),
|
||||
context.output_info.clone(),
|
||||
context.primary_handle,
|
||||
context.active_handle,
|
||||
) {
|
||||
if let Err(err) = callback.apply_to(component.component_instance()) {
|
||||
);
|
||||
|
||||
for callback in &context.callbacks {
|
||||
if let Err(err) =
|
||||
callback.apply_with_context(component.component_instance(), &callback_context)
|
||||
{
|
||||
info!(
|
||||
"Failed to register lock callback '{}': {err}",
|
||||
callback.name()
|
||||
);
|
||||
} else {
|
||||
} else if callback.should_apply(&callback_context) {
|
||||
info!("Registered lock callback '{}'", callback.name());
|
||||
}
|
||||
} else {
|
||||
info!(
|
||||
"Skipping callback '{}' due to selector filter (output {:?})",
|
||||
|
|
@ -156,15 +175,35 @@ impl ActiveLockSurface {
|
|||
}
|
||||
|
||||
pub fn apply_callback(&self, callback: &LockCallback) {
|
||||
if let Some(component) = self.component.as_ref() {
|
||||
if let Err(err) = callback.apply_to(component.component_instance()) {
|
||||
let Some(component) = self.component.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(component_name) = &self.component_name else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(output_handle) = self.output_handle else {
|
||||
return;
|
||||
};
|
||||
|
||||
let callback_context = LockCallbackContext::new(
|
||||
component_name.clone(),
|
||||
output_handle,
|
||||
self.output_info.clone(),
|
||||
self.primary_handle,
|
||||
self.active_handle,
|
||||
);
|
||||
|
||||
if let Err(err) =
|
||||
callback.apply_with_context(component.component_instance(), &callback_context)
|
||||
{
|
||||
info!(
|
||||
"Failed to register lock callback '{}': {err}",
|
||||
callback.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn scaling_mode(&self) -> LockScalingMode {
|
||||
if self.surface.has_fractional_scale() && self.surface.has_viewport() {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ use crate::wayland::globals::context::GlobalContext;
|
|||
use crate::wayland::managed_proxies::{ManagedWlKeyboard, ManagedWlPointer};
|
||||
use crate::wayland::outputs::{OutputManager, OutputMapping};
|
||||
use crate::wayland::session_lock::lock_context::SessionLockContext;
|
||||
use crate::wayland::session_lock::manager::callbacks::{
|
||||
create_lock_callback, create_lock_callback_with_output_filter,
|
||||
};
|
||||
use crate::wayland::session_lock::{LockCallback, OutputFilter, SessionLockManager};
|
||||
use layer_shika_domain::entities::output_registry::OutputRegistry;
|
||||
use layer_shika_domain::value_objects::handle::SurfaceHandle;
|
||||
|
|
@ -138,7 +141,7 @@ impl AppState {
|
|||
callback_name: impl Into<String>,
|
||||
handler: SessionLockCallback,
|
||||
) {
|
||||
let callback = LockCallback::new(callback_name, handler);
|
||||
let callback = create_lock_callback(callback_name, handler);
|
||||
if let Some(manager) = self.lock_manager.as_mut() {
|
||||
manager.register_callback(callback.clone());
|
||||
}
|
||||
|
|
@ -151,7 +154,13 @@ impl AppState {
|
|||
handler: SessionLockCallback,
|
||||
filter: OutputFilter,
|
||||
) {
|
||||
let callback = LockCallback::with_filter(callback_name, handler, filter);
|
||||
let callback = create_lock_callback_with_output_filter(
|
||||
callback_name,
|
||||
handler,
|
||||
move |component_name, output_handle, output_info, primary, active| {
|
||||
filter(component_name, output_handle, output_info, primary, active)
|
||||
},
|
||||
);
|
||||
if let Some(manager) = self.lock_manager.as_mut() {
|
||||
manager.register_callback(callback.clone());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue