refactor: surface dimensions spec compliance

This commit is contained in:
drendog 2025-12-29 00:13:40 +01:00
parent 0f5bd88742
commit 22aa14417b
Signed by: dwenya
GPG key ID: 8DD77074645332D0
3 changed files with 59 additions and 24 deletions

View file

@ -405,6 +405,10 @@ impl Shell {
}));
}
for def in &definitions {
def.config.validate().map_err(Error::Domain)?;
}
let is_single_window = definitions.len() == 1;
if is_single_window {
@ -693,6 +697,12 @@ impl Shell {
config: &SurfaceConfig,
) {
log::debug!("Surface command: ApplyConfig {:?}", target);
if let Err(e) = config.validate() {
log::error!("Invalid surface configuration: {}", e);
return;
}
for surface in Self::resolve_surface_target(ctx, target) {
let handle = LayerSurfaceHandle::from_window_state(surface);

View file

@ -1,4 +1,5 @@
use crate::dimensions::ScaleFactor;
use crate::errors::{DomainError, Result};
use crate::value_objects::anchor::AnchorEdges;
use crate::value_objects::dimensions::SurfaceDimension;
use crate::value_objects::keyboard_interactivity::KeyboardInteractivity;
@ -10,6 +11,14 @@ use crate::value_objects::output_policy::OutputPolicy;
///
/// Contains all positioning, sizing, and behavioral properties for a surface.
/// Use with `ShellConfig` for declarative configuration or build via `ShellBuilder`.
///
/// # Wayland Protocol Requirements
///
/// According to the wlr-layer-shell protocol, dimensions and anchors must be coordinated:
/// - If width is 0, the surface must be anchored to both left and right edges
/// - If height is 0, the surface must be anchored to both top and bottom edges
///
/// Use `validate()` to check protocol compliance before use.
#[derive(Debug, Clone)]
pub struct SurfaceConfig {
pub dimensions: SurfaceDimension,
@ -38,6 +47,33 @@ impl SurfaceConfig {
output_policy: OutputPolicy::default(),
}
}
/// Validates the surface configuration according to Wayland layer-shell protocol requirements.
///
/// According to the protocol:
/// - If width is 0, the surface must be anchored to both left and right edges
/// - If height is 0, the surface must be anchored to both top and bottom edges
pub fn validate(&self) -> Result<()> {
if self.dimensions.width() == 0 && !(self.anchor.has_left() && self.anchor.has_right()) {
return Err(DomainError::Configuration {
message: "Width is 0 but surface is not anchored to both left and right edges. \
According to wlr-layer-shell protocol, you must set your anchor to \
opposite edges in the dimensions you omit."
.to_string(),
});
}
if self.dimensions.height() == 0 && !(self.anchor.has_top() && self.anchor.has_bottom()) {
return Err(DomainError::Configuration {
message: "Height is 0 but surface is not anchored to both top and bottom edges. \
According to wlr-layer-shell protocol, you must set your anchor to \
opposite edges in the dimensions you omit."
.to_string(),
});
}
Ok(())
}
}
impl Default for SurfaceConfig {

View file

@ -1,26 +1,24 @@
/// Width and height of a layer surface in pixels
///
/// Use 0 for either dimension to let the surface stretch along that axis based on anchor edges.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// According to the Wayland wlr-layer-shell protocol:
/// - Pass 0 for either width or height to have the compositor assign it
/// - The compositor will center the surface with respect to its anchors
/// - When using 0, you MUST anchor to opposite edges in that dimension:
/// - width = 0 requires both left and right anchors
/// - height = 0 requires both top and bottom anchors
/// - Not following this requirement is a protocol error
/// - Both values default to 0
///
/// Size is double-buffered via `wl_surface.commit`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct SurfaceDimension {
width: u32,
height: u32,
}
impl SurfaceDimension {
pub fn new(width: u32, height: u32) -> Self {
Self {
width: if width == 0 {
Self::default().width
} else {
width
},
height: if height == 0 {
Self::default().height
} else {
height
},
}
pub const fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
pub const fn from_raw(width: u32, height: u32) -> Self {
@ -36,15 +34,6 @@ impl SurfaceDimension {
}
}
impl Default for SurfaceDimension {
fn default() -> Self {
Self {
width: 20,
height: 20,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct PopupDimensions {
pub width: f32,