diff --git a/tools/ferese-effects-probe/src/main.rs b/tools/ferese-effects-probe/src/main.rs index 47ce1c8..47398a7 100644 --- a/tools/ferese-effects-probe/src/main.rs +++ b/tools/ferese-effects-probe/src/main.rs @@ -111,6 +111,9 @@ struct ProbeState { layer_surface: Option, effects: Option, buffer: Option, + preview_backdrop_surface: Option, + preview_backdrop_layer: Option, + preview_backdrop_buffer: Option, preview: bool, configured: bool, closed: bool, @@ -168,6 +171,29 @@ impl ProbeState { effects.set_role(ferese_surface_effects_v1::Role::Panel); surface.commit(); + + if self.preview { + let backdrop_surface = compositor.create_surface(qh, ()); + let backdrop_layer = layer_shell.get_layer_surface( + &backdrop_surface, + None, + zwlr_layer_shell_v1::Layer::Top, + "ferese-effects-preview-backdrop".to_owned(), + qh, + (), + ); + backdrop_layer.set_anchor( + zwlr_layer_surface_v1::Anchor::Top | zwlr_layer_surface_v1::Anchor::Right, + ); + backdrop_layer.set_margin(12, 12, 0, 0); + backdrop_layer.set_size(520, 260); + backdrop_layer.set_exclusive_zone(0); + backdrop_surface.commit(); + + self.preview_backdrop_surface = Some(backdrop_surface); + self.preview_backdrop_layer = Some(backdrop_layer); + } + self.surface = Some(surface); self.layer_surface = Some(layer_surface); self.effects = Some(effects); @@ -207,6 +233,48 @@ fn create_buffer( Ok(buffer) } +fn create_preview_backdrop_buffer( + shm: &wl_shm::WlShm, + qh: &QueueHandle, + width: u32, + height: u32, +) -> Result> { + let stride = width * 4; + let size = stride * height; + let mut file = tempfile::tempfile()?; + file.set_len(u64::from(size))?; + + for y in 0..height { + for x in 0..width { + let checker = (x / 11 + y / 11) % 2 == 0; + let stripe = (x / 53) % 3; + let pixel = match (checker, stripe) { + (true, 0) => [0xf0, 0xf0, 0xf0, 0xff], + (false, 0) => [0x08, 0x08, 0x08, 0xff], + (true, 1) => [0x30, 0xe8, 0x40, 0xff], + (false, 1) => [0x10, 0x18, 0x08, 0xff], + (true, _) => [0x30, 0x60, 0xf0, 0xff], + (false, _) => [0x18, 0x08, 0x20, 0xff], + }; + file.write_all(&pixel)?; + } + } + file.seek(SeekFrom::Start(0))?; + + let pool = shm.create_pool(file.as_fd(), size as i32, qh, ()); + let buffer = pool.create_buffer( + 0, + width as i32, + height as i32, + stride as i32, + wl_shm::Format::Argb8888, + qh, + (), + ); + pool.destroy(); + Ok(buffer) +} + impl Dispatch for ProbeState { fn event( state: &mut Self, @@ -255,6 +323,24 @@ impl Dispatch for ProbeState { height, } => { layer_surface.ack_configure(serial); + + if state.preview_backdrop_layer.as_ref() == Some(layer_surface) { + let width = if width == 0 { 520 } else { width }; + let height = if height == 0 { 260 } else { height }; + let surface = state + .preview_backdrop_surface + .clone() + .expect("preview backdrop surface initialized"); + let shm = state.shm.as_ref().expect("shm initialized"); + let buffer = create_preview_backdrop_buffer(shm, qh, width, height) + .expect("create preview backdrop buffer"); + surface.attach(Some(&buffer), 0, 0); + surface.damage_buffer(0, 0, width as i32, height as i32); + surface.commit(); + state.preview_backdrop_buffer = Some(buffer); + return; + } + state.configure_count = state.configure_count.saturating_add(1); state.width = if width == 0 { WIDTH } else { width }; state.height = if height == 0 { HEIGHT } else { height };