diff --git a/Cargo.toml b/Cargo.toml index e8d7c335f..f54476513 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ thiserror = "2.0.12" wayland-backend = "0.3.0" wayland-client = "0.31.1" wayland-cursor = "0.31.0" -wayland-protocols = { version = "0.32.1", features = ["client", "staging", "unstable"] } +wayland-protocols = { version = "0.32.9", features = ["client", "staging", "unstable"] } wayland-protocols-experimental = { version = "20251230.0.1", features = ["client"] } wayland-protocols-misc = { version = "0.3.6", features = ["client"] } wayland-protocols-wlr = { version = "0.3.1", features = ["client"] } diff --git a/src/background_effect.rs b/src/background_effect.rs new file mode 100644 index 000000000..764cb3b0b --- /dev/null +++ b/src/background_effect.rs @@ -0,0 +1,122 @@ +use wayland_client::{ + globals::GlobalList, protocol::wl_surface, Connection, Dispatch, QueueHandle, WEnum, +}; +use wayland_protocols::ext::background_effect::v1::client::{ + ext_background_effect_manager_v1, ext_background_effect_surface_v1, +}; + +use crate::{error::GlobalError, globals::GlobalData, registry::GlobalProxy}; + +#[derive(Debug)] +pub struct BackgroundEffectState { + manager: GlobalProxy, + capabilities: Option, +} + +impl BackgroundEffectState { + pub fn new(globals: &GlobalList, qh: &QueueHandle) -> Self + where + D: Dispatch + + 'static, + { + let manager = GlobalProxy::from(globals.bind(qh, 1..=1, GlobalData)); + Self { manager, capabilities: None } + } + + /// Capabilities advertised by the compositor. + /// + /// Returns `None` if the compositor has not yet advertised capabilities. + pub fn capabilities(&self) -> Option { + self.capabilities + } + + /// Get `ext_background_effect_surface_v1` for a given `wl_surface`. + /// + /// Returns error if `ext_background_effect_manager_v1` global is not present. + pub fn get_background_effect( + &self, + surface: &wl_surface::WlSurface, + qh: &QueueHandle, + ) -> Result + where + D: Dispatch + + 'static, + { + Ok(self.manager.get()?.get_background_effect(surface, qh, GlobalData)) + } + + /// The `ext_background_effect_manager_v1` global, if any. + pub fn ext_background_effect_manager_v1( + &self, + ) -> Result<&ext_background_effect_manager_v1::ExtBackgroundEffectManagerV1, GlobalError> { + self.manager.get() + } +} + +pub trait BackgroundEffectHandler { + fn background_effect_state(&mut self) -> &mut BackgroundEffectState; + + /// Compositor has advertised background effect capabilities. + /// + /// Call [`BackgroundEffectState::capabilities`] to access capabilities. + fn update_capabilities(&mut self); +} + +impl Dispatch + for BackgroundEffectState +where + D: Dispatch + + BackgroundEffectHandler, +{ + fn event( + data: &mut D, + _manager: &ext_background_effect_manager_v1::ExtBackgroundEffectManagerV1, + event: ext_background_effect_manager_v1::Event, + _: &GlobalData, + _conn: &Connection, + _qh: &QueueHandle, + ) { + match event { + ext_background_effect_manager_v1::Event::Capabilities { flags } => { + let flags = match flags { + WEnum::Value(value) => value, + WEnum::Unknown(value) => { + ext_background_effect_manager_v1::Capability::from_bits_retain(value) + } + }; + data.background_effect_state().capabilities = Some(flags); + data.update_capabilities(); + } + _ => unreachable!(), + } + } +} + +impl Dispatch + for BackgroundEffectState +where + D: Dispatch, +{ + fn event( + _data: &mut D, + _surface: &ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1, + _event: ext_background_effect_surface_v1::Event, + _: &GlobalData, + _conn: &Connection, + _qh: &QueueHandle, + ) { + unreachable!() + } +} + +#[macro_export] +macro_rules! delegate_background_effect { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::reexports::protocols::ext::background_effect::v1::client::ext_background_effect_manager_v1::ExtBackgroundEffectManagerV1: $crate::globals::GlobalData + ] => $crate::background_effect::BackgroundEffectState); + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::reexports::protocols::ext::background_effect::v1::client::ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1: $crate::globals::GlobalData + ] => $crate::background_effect::BackgroundEffectState); + }; +} diff --git a/src/lib.rs b/src/lib.rs index 6e345fda5..a0d0f10a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ pub mod reexports { } pub mod activation; +pub mod background_effect; pub mod compositor; pub mod data_device_manager; pub mod dmabuf;