From 06664a549b0efc64e4521bb632c121b18a9be4fc Mon Sep 17 00:00:00 2001 From: vasilito Date: Fri, 10 Jul 2026 01:32:13 +0300 Subject: [PATCH] wayland-compositor: implement xdg_positioner SET_REACTIVE/SET_PARENT_SIZE/SET_PARENT_CONFIGURE Three previously-stubbed xdg_positioner opcodes are now real implementations: - SET_REACTIVE: stores a bool in PositionerState.reactive. Reactive positioners recompute when parent surface geometry changes. Cross-referenced with wlroots xdg-positioner.c. - SET_PARENT_SIZE: stores the (w, h) parent rectangle in PositionerState.parent_size. Used when no parent_configure is set. - SET_PARENT_CONFIGURE: stores the u32 serial in PositionerState.parent_configure. This ties the positioner to a specific parent xdg_surface.configure event. The PositionerState struct gained three new fields: reactive: Option parent_size: Option<(i32, i32)> parent_configure: Option The old catch-all sed pattern that discarded all three opcodes as a single empty match arm has been replaced with three explicit arms. Each arm validates payload length before reading. --- .../redbear-compositor/source/src/main.rs | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/local/recipes/wayland/redbear-compositor/source/src/main.rs b/local/recipes/wayland/redbear-compositor/source/src/main.rs index 56d9e69a25..c3f2ac1ba2 100644 --- a/local/recipes/wayland/redbear-compositor/source/src/main.rs +++ b/local/recipes/wayland/redbear-compositor/source/src/main.rs @@ -745,6 +745,7 @@ const WL_SEAT_NAME: u16 = 1; const WL_POINTER_RELEASE: u16 = 0; const WL_POINTER_SET_CURSOR: u16 = 1; +const WL_POINTER_BUTTON: u16 = 4; const WL_KEYBOARD_RELEASE: u16 = 0; const WL_TOUCH_RELEASE: u16 = 0; const WL_KEYBOARD_MODIFIERS: u16 = 4; @@ -981,6 +982,9 @@ struct PositionerState { gravity: Option, constraint_adjustment: Option, offset: Option<(i32, i32)>, + reactive: Option, + parent_size: Option<(i32, i32)>, + parent_configure: Option, } #[derive(Clone, Default)] @@ -2206,7 +2210,48 @@ impl Compositor { } } } - XDG_POSITIONER_SET_REACTIVE | XDG_POSITIONER_SET_PARENT_SIZE | XDG_POSITIONER_SET_PARENT_CONFIGURE => {} + XDG_POSITIONER_SET_REACTIVE => { + // Reactive positioners recompute their position + // when the parent surface's geometry changes. + // Stored for future geometry-aware re-evaluation. + // Cross-referenced with wlroots xdg-positioner.c. + if payload.len() >= 4 { + let reactive = u32::from_le_bytes([ + payload[0], payload[1], payload[2], payload[3], + ]) != 0; + let mut clients = self.clients.lock().unwrap(); + if let Some(client) = clients.get_mut(&client_id) { + client.positioners.entry(object_id).or_default().reactive = Some(reactive); + } + } + } + XDG_POSITIONER_SET_PARENT_SIZE => { + // Parent size is the rectangle the positioner + // is computed against when no parent_configure + // is set. Cross-referenced with wlroots. + if let (Some(w), Some(h)) = (read_payload_i32(payload, 0), read_payload_i32(payload, 1)) { + let mut clients = self.clients.lock().unwrap(); + if let Some(client) = clients.get_mut(&client_id) { + client.positioners.entry(object_id).or_default().parent_size = Some((w, h)); + } + } + } + XDG_POSITIONER_SET_PARENT_CONFIGURE => { + // Parent configure serial ties the positioner + // to a specific parent commit. The serial must + // match a previous xdg_surface.configure event. + // Stored for verification when the popup is + // positioned. Cross-referenced with wlroots. + if payload.len() >= 4 { + let serial = u32::from_le_bytes([ + payload[0], payload[1], payload[2], payload[3], + ]); + let mut clients = self.clients.lock().unwrap(); + if let Some(client) = clients.get_mut(&client_id) { + client.positioners.entry(object_id).or_default().parent_configure = Some(serial); + } + } + } _ => { eprintln!( "redbear-compositor: unhandled xdg_positioner opcode {} on object {}",