diff --git a/src/ifs/wl_compositor.rs b/src/ifs/wl_compositor.rs index 4ad23cc9..0156c46a 100644 --- a/src/ifs/wl_compositor.rs +++ b/src/ifs/wl_compositor.rs @@ -20,7 +20,7 @@ pub struct WlCompositorGlobal { pub struct WlCompositor { id: WlCompositorId, client: Rc, - _version: u32, + version: u32, pub tracker: Tracker, } @@ -38,7 +38,7 @@ impl WlCompositorGlobal { let obj = Rc::new(WlCompositor { id, client: client.clone(), - _version: version, + version, tracker: Default::default(), }); track!(client, obj); @@ -50,7 +50,7 @@ impl WlCompositorGlobal { impl WlCompositor { fn create_surface(&self, parser: MsgParser<'_, '_>) -> Result<(), WlCompositorError> { let surface: CreateSurface = self.client.parse(self, parser)?; - let surface = Rc::new(WlSurface::new(surface.id, &self.client)); + let surface = Rc::new(WlSurface::new(surface.id, &self.client, self.version)); track!(self.client, surface); self.client.add_client_obj(&surface)?; if self.client.is_xwayland { @@ -80,7 +80,7 @@ impl Global for WlCompositorGlobal { } fn version(&self) -> u32 { - 4 + 6 } } diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index ad6d493e..1e2f0ab0 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -75,6 +75,9 @@ const INVALID_TRANSFORM: u32 = 1; #[allow(dead_code)] const INVALID_SIZE: u32 = 2; +const OFFSET_SINCE: u32 = 5; +const BUFFER_SCALE_SINCE: u32 = 6; + #[derive(Copy, Clone, Debug, PartialEq)] enum Transform { Normal, @@ -209,7 +212,7 @@ impl SurfaceRole { pub struct SurfaceSendPreferredScaleVisitor; impl NodeVisitorBase for SurfaceSendPreferredScaleVisitor { fn visit_surface(&mut self, node: &Rc) { - node.send_preferred_scale(); + node.on_scale_change(); node.node_visit_children(self); } } @@ -252,6 +255,7 @@ pub struct WlSurface { xwayland_serial: Cell>, tearing_control: CloneCell>>, tearing: Cell, + version: u32, } impl Debug for WlSurface { @@ -333,7 +337,8 @@ impl SurfaceExt for NoneSurfaceExt { #[derive(Default)] struct PendingState { - buffer: Cell)>>>, + buffer: Cell>>>, + offset: Cell<(i32, i32)>, opaque_region: Cell>>>, input_region: Cell>>>, frame_request: RefCell>>, @@ -360,7 +365,7 @@ pub struct StackElement { } impl WlSurface { - pub fn new(id: WlSurfaceId, client: &Rc) -> Self { + pub fn new(id: WlSurfaceId, client: &Rc, version: u32) -> Self { Self { id, node_id: client.state.node_ids.next(), @@ -399,6 +404,7 @@ impl WlSurface { xwayland_serial: Default::default(), tearing_control: Default::default(), tearing: Cell::new(false), + version, } } @@ -427,9 +433,7 @@ impl WlSurface { output.global.send_enter(self); old.global.send_leave(self); if old.preferred_scale.get() != output.preferred_scale.get() { - if let Some(fs) = self.fractional_scale.get() { - fs.send_preferred_scale(); - } + self.on_scale_change(); } let children = self.children.borrow_mut(); if let Some(children) = &*children { @@ -439,10 +443,11 @@ impl WlSurface { } } - pub fn send_preferred_scale(&self) { + fn on_scale_change(&self) { if let Some(fs) = self.fractional_scale.get() { fs.send_preferred_scale(); } + self.send_preferred_buffer_scale(); } pub fn get_toplevel(&self) -> Option> { @@ -513,6 +518,15 @@ impl WlSurface { }) } + pub fn send_preferred_buffer_scale(&self) { + if self.version >= BUFFER_SCALE_SINCE { + self.client.event(PreferredBufferScale { + self_id: self.id, + factor: self.output.get().global.legacy_scale.get() as _, + }); + } + } + fn set_toplevel(&self, tl: Option>) { let ch = self.children.borrow(); if let Some(ch) = &*ch { @@ -640,8 +654,15 @@ impl WlSurface { fn attach(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), WlSurfaceError> { let req: Attach = self.parse(parser)?; + if self.version >= OFFSET_SINCE { + if req.x != 0 || req.y != 0 { + return Err(WlSurfaceError::OffsetInAttach); + } + } else { + self.pending.offset.set((req.x, req.y)); + } let buf = if req.buffer.is_some() { - Some((req.x, req.y, self.client.lookup(req.buffer)?)) + Some(self.client.lookup(req.buffer)?) } else { None }; @@ -729,6 +750,7 @@ impl WlSurface { } let mut buffer_changed = false; let mut old_raw_size = None; + let (dx, dy) = self.pending.offset.take(); if let Some(buffer_change) = self.pending.buffer.take() { buffer_changed = true; if let Some(buffer) = self.buffer.take() { @@ -737,7 +759,7 @@ impl WlSurface { buffer.send_release(); } } - if let Some((dx, dy, buffer)) = buffer_change { + if let Some(buffer) = buffer_change { let _ = buffer.update_texture(); self.buffer.set(Some(buffer)); self.buf_x.fetch_add(dx); @@ -909,6 +931,12 @@ impl WlSurface { Ok(()) } + fn offset(&self, parser: MsgParser<'_, '_>) -> Result<(), WlSurfaceError> { + let req: Offset = self.parse(parser)?; + self.pending.offset.set((req.x, req.y)); + Ok(()) + } + fn find_surface_at(self: &Rc, x: i32, y: i32) -> Option<(Rc, i32, i32)> { let rect = self.buffer_abs_pos.get().at_point(0, 0); let children = self.children.borrow(); @@ -1033,11 +1061,12 @@ object_base! { SET_BUFFER_TRANSFORM => set_buffer_transform, SET_BUFFER_SCALE => set_buffer_scale, DAMAGE_BUFFER => damage_buffer, + OFFSET => offset, } impl Object for WlSurface { fn num_requests(&self) -> u32 { - DAMAGE_BUFFER + 1 + OFFSET + 1 } fn break_loops(&self) { @@ -1227,6 +1256,8 @@ pub enum WlSurfaceError { NonIntegerViewportSize, #[error("Viewport source is not contained in the attached buffer")] ViewportOutsideBuffer, + #[error("attach request must not contain offset")] + OffsetInAttach, } efrom!(WlSurfaceError, ClientError); efrom!(WlSurfaceError, XdgSurfaceError); diff --git a/wire/wl_surface.txt b/wire/wl_surface.txt index 2a3f98f2..46b27eb0 100644 --- a/wire/wl_surface.txt +++ b/wire/wl_surface.txt @@ -60,3 +60,11 @@ msg enter = 0 { msg leave = 1 { output: id(wl_output), } + +msg preferred_buffer_scale = 2 { + factor: i32, +} + +msg preferred_buffer_transform = 3 { + transform: u32, +}