1
0
Fork 0
forked from wry/wry

surface: commit subsurface state during parent commit

This commit is contained in:
Julian Orth 2024-04-04 10:28:30 +02:00
parent a2c907c8c4
commit c5fd2cd989
10 changed files with 125 additions and 69 deletions

View file

@ -287,8 +287,8 @@ trait SurfaceExt {
Ok(()) Ok(())
} }
fn after_apply_commit(self: Rc<Self>, pending: &mut PendingState) { fn after_apply_commit(self: Rc<Self>) {
let _ = pending; // nothing
} }
fn is_some(&self) -> bool { fn is_some(&self) -> bool {
@ -336,7 +336,7 @@ trait SurfaceExt {
surface: &WlSurface, surface: &WlSurface,
child: SubsurfaceId, child: SubsurfaceId,
consume: &mut dyn FnMut( consume: &mut dyn FnMut(
OccupiedEntry<SubsurfaceId, CommittedSubsurface>, OccupiedEntry<SubsurfaceId, AttachedSubsurfaceState>,
) -> Result<(), WlSurfaceError>, ) -> Result<(), WlSurfaceError>,
) -> Result<(), WlSurfaceError> { ) -> Result<(), WlSurfaceError> {
surface.pending.borrow_mut().consume_child(child, consume) surface.pending.borrow_mut().consume_child(child, consume)
@ -367,18 +367,17 @@ struct PendingState {
xwayland_serial: Option<u64>, xwayland_serial: Option<u64>,
tearing: Option<bool>, tearing: Option<bool>,
content_type: Option<Option<ContentType>>, content_type: Option<Option<ContentType>>,
subsurface: Option<Box<PendingSubsurfaceData>>,
xdg_surface: Option<Box<PendingXdgSurfaceData>>, xdg_surface: Option<Box<PendingXdgSurfaceData>>,
layer_surface: Option<Box<PendingLayerSurfaceData>>, layer_surface: Option<Box<PendingLayerSurfaceData>>,
subsurfaces: AHashMap<SubsurfaceId, CommittedSubsurface>, subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
acquire_point: Option<(Rc<SyncObj>, SyncObjPoint)>, acquire_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
release_point: Option<(Rc<SyncObj>, SyncObjPoint)>, release_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
explicit_sync: bool, explicit_sync: bool,
} }
struct CommittedSubsurface { struct AttachedSubsurfaceState {
subsurface: Rc<WlSubsurface>, subsurface: Rc<WlSubsurface>,
state: Box<PendingState>, pending: PendingSubsurfaceData,
} }
impl PendingState { impl PendingState {
@ -445,13 +444,12 @@ impl PendingState {
} }
}; };
} }
merge_ext!(subsurface);
merge_ext!(xdg_surface); merge_ext!(xdg_surface);
merge_ext!(layer_surface); merge_ext!(layer_surface);
for (id, mut state) in next.subsurfaces.drain() { for (id, mut state) in next.subsurfaces.drain() {
match self.subsurfaces.entry(id) { match self.subsurfaces.entry(id) {
Entry::Occupied(mut o) => { Entry::Occupied(mut o) => {
o.get_mut().state.merge(&mut state.state, client); o.get_mut().pending.merge(&mut state.pending, client);
} }
Entry::Vacant(v) => { Entry::Vacant(v) => {
v.insert(state); v.insert(state);
@ -464,7 +462,7 @@ impl PendingState {
&mut self, &mut self,
child: SubsurfaceId, child: SubsurfaceId,
consume: impl FnOnce( consume: impl FnOnce(
OccupiedEntry<SubsurfaceId, CommittedSubsurface>, OccupiedEntry<SubsurfaceId, AttachedSubsurfaceState>,
) -> Result<(), WlSurfaceError>, ) -> Result<(), WlSurfaceError>,
) -> Result<(), WlSurfaceError> { ) -> Result<(), WlSurfaceError> {
match self.subsurfaces.entry(child) { match self.subsurfaces.entry(child) {
@ -851,11 +849,8 @@ impl WlSurface {
} }
fn apply_state(self: &Rc<Self>, pending: &mut PendingState) -> Result<(), WlSurfaceError> { fn apply_state(self: &Rc<Self>, pending: &mut PendingState) -> Result<(), WlSurfaceError> {
for (_, mut subsurface) in pending.subsurfaces.drain() { for (_, pending) in &mut pending.subsurfaces {
subsurface pending.subsurface.apply_state(&mut pending.pending)?;
.subsurface
.surface
.apply_state(&mut subsurface.state)?;
} }
if self.destroyed.get() { if self.destroyed.get() {
return Ok(()); return Ok(());
@ -1056,7 +1051,7 @@ impl WlSurface {
cursor.update_hardware_cursor(); cursor.update_hardware_cursor();
} }
} }
self.ext.get().after_apply_commit(pending); self.ext.get().after_apply_commit();
self.client.state.damage(); self.client.state.damage();
Ok(()) Ok(())
} }
@ -1274,7 +1269,7 @@ impl WlSurface {
&self, &self,
child: SubsurfaceId, child: SubsurfaceId,
mut consume: impl FnMut( mut consume: impl FnMut(
OccupiedEntry<SubsurfaceId, CommittedSubsurface>, OccupiedEntry<SubsurfaceId, AttachedSubsurfaceState>,
) -> Result<(), WlSurfaceError>, ) -> Result<(), WlSurfaceError>,
) -> Result<(), WlSurfaceError> { ) -> Result<(), WlSurfaceError> {
self.ext self.ext

View file

@ -269,7 +269,9 @@ fn consume_acquire_points(pending: &mut PendingState, points: &mut SmallVec<[Poi
points.push(point); points.push(point);
} }
for ss in pending.subsurfaces.values_mut() { for ss in pending.subsurfaces.values_mut() {
consume_acquire_points(&mut ss.state, points); if let Some(state) = &mut ss.pending.state {
consume_acquire_points(state, points);
}
} }
} }
@ -290,6 +292,8 @@ fn set_effective_timeline(
} }
} }
for ss in pending.subsurfaces.values() { for ss in pending.subsurfaces.values() {
set_effective_timeline(&ss.subsurface.surface.commit_timeline, &ss.state, effective); if let Some(state) = &ss.pending.state {
set_effective_timeline(&ss.subsurface.surface.commit_timeline, state, effective);
}
} }
} }

View file

@ -1,9 +1,9 @@
use { use {
crate::{ crate::{
client::ClientError, client::{Client, ClientError},
ifs::wl_surface::{ ifs::wl_surface::{
CommitAction, CommittedSubsurface, PendingState, StackElement, SurfaceExt, SurfaceRole, AttachedSubsurfaceState, CommitAction, PendingState, StackElement, SurfaceExt,
WlSurface, WlSurfaceError, WlSurfaceId, SurfaceRole, WlSurface, WlSurfaceError, WlSurfaceId,
}, },
leaks::Tracker, leaks::Tracker,
object::Object, object::Object,
@ -13,13 +13,12 @@ use {
clonecell::CloneCell, clonecell::CloneCell,
linkedlist::{LinkedNode, NodeRef}, linkedlist::{LinkedNode, NodeRef},
numcell::NumCell, numcell::NumCell,
option_ext::OptionExt,
}, },
wire::{wl_subsurface::*, WlSubsurfaceId}, wire::{wl_subsurface::*, WlSubsurfaceId},
}, },
std::{ std::{
cell::{Cell, RefCell, RefMut}, cell::{Cell, RefCell, RefMut},
collections::hash_map::{Entry, OccupiedEntry}, collections::hash_map::OccupiedEntry,
mem, mem,
ops::Deref, ops::Deref,
rc::Rc, rc::Rc,
@ -51,12 +50,20 @@ pub struct WlSubsurface {
#[derive(Default)] #[derive(Default)]
pub struct PendingSubsurfaceData { pub struct PendingSubsurfaceData {
pub(super) state: Option<Box<PendingState>>,
node: Option<LinkedNode<StackElement>>, node: Option<LinkedNode<StackElement>>,
position: Option<(i32, i32)>, position: Option<(i32, i32)>,
} }
impl PendingSubsurfaceData { impl PendingSubsurfaceData {
pub fn merge(&mut self, next: &mut Self) { pub fn merge(&mut self, next: &mut Self, client: &Rc<Client>) {
if let Some(mut new) = next.state.take() {
match &mut self.state {
Some(old) => old.merge(&mut new, client),
_ => self.state = Some(new),
}
}
macro_rules! opt { macro_rules! opt {
($name:ident) => { ($name:ident) => {
if let Some(n) = next.$name.take() { if let Some(n) = next.$name.take() {
@ -107,12 +114,35 @@ impl WlSubsurface {
} }
} }
fn pending(&self) -> RefMut<Box<PendingSubsurfaceData>> { fn pending<'a>(self: &'a Rc<Self>) -> RefMut<'a, PendingSubsurfaceData> {
RefMut::map(self.surface.pending.borrow_mut(), |m| { RefMut::map(self.parent.pending.borrow_mut(), |m| {
m.subsurface.get_or_insert_default_ext() &mut m
.subsurfaces
.entry(self.unique_id)
.or_insert_with(|| AttachedSubsurfaceState {
subsurface: self.clone(),
pending: Default::default(),
})
.pending
}) })
} }
pub fn apply_state(&self, pending: &mut PendingSubsurfaceData) -> Result<(), WlSurfaceError> {
if let Some(state) = &mut pending.state.take() {
self.surface.apply_state(state)?;
}
if let Some(v) = pending.node.take() {
v.pending.set(false);
self.node.borrow_mut().replace(v);
}
if let Some((x, y)) = pending.position.take() {
self.position
.set(self.surface.buffer_abs_pos.get().at_point(x, y));
self.parent.need_extents_update.set(true);
}
Ok(())
}
pub fn install(self: &Rc<Self>) -> Result<(), WlSubsurfaceError> { pub fn install(self: &Rc<Self>) -> Result<(), WlSubsurfaceError> {
if self.surface.id == self.parent.id { if self.surface.id == self.parent.id {
return Err(WlSubsurfaceError::OwnParent(self.surface.id)); return Err(WlSubsurfaceError::OwnParent(self.surface.id));
@ -158,9 +188,12 @@ impl WlSubsurface {
let _req: Destroy = self.surface.client.parse(self, parser)?; let _req: Destroy = self.surface.client.parse(self, parser)?;
self.surface.unset_ext(); self.surface.unset_ext();
self.parent.consume_pending_child(self.unique_id, |oe| { self.parent.consume_pending_child(self.unique_id, |oe| {
self.surface.apply_state(&mut oe.remove().state) let oe = oe.remove();
if let Some(mut state) = oe.pending.state {
self.surface.apply_state(&mut state)?;
}
Ok(())
})?; })?;
self.surface.pending.borrow_mut().subsurface.take();
*self.node.borrow_mut() = None; *self.node.borrow_mut() = None;
self.latest_node.take(); self.latest_node.take();
{ {
@ -184,8 +217,8 @@ impl WlSubsurface {
Ok(()) Ok(())
} }
fn set_position(&self, parser: MsgParser<'_, '_>) -> Result<(), WlSubsurfaceError> { fn set_position(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), WlSubsurfaceError> {
let req: SetPosition = self.surface.client.parse(self, parser)?; let req: SetPosition = self.surface.client.parse(&**self, parser)?;
self.pending().position = Some((req.x, req.y)); self.pending().position = Some((req.x, req.y));
Ok(()) Ok(())
} }
@ -270,14 +303,12 @@ impl WlSubsurface {
} }
fn on_desync(&self) -> Result<(), WlSurfaceError> { fn on_desync(&self) -> Result<(), WlSurfaceError> {
let committed = self let committed = &mut *self.parent.pending.borrow_mut();
.parent let committed = committed.subsurfaces.get_mut(&self.unique_id);
.pending if let Some(ps) = committed {
.borrow_mut() if let Some(mut state) = ps.pending.state.take() {
.subsurfaces self.surface.apply_state(&mut state)?;
.remove(&self.unique_id); }
if let Some(mut ps) = committed {
self.surface.apply_state(&mut ps.state)?;
} }
Ok(()) Ok(())
} }
@ -318,35 +349,17 @@ simple_add_obj!(WlSubsurface);
impl SurfaceExt for WlSubsurface { impl SurfaceExt for WlSubsurface {
fn commit_requested(self: Rc<Self>, pending: &mut Box<PendingState>) -> CommitAction { fn commit_requested(self: Rc<Self>, pending: &mut Box<PendingState>) -> CommitAction {
if self.sync() { if self.sync() {
let mut parent_pending = self.parent.pending.borrow_mut(); let mut parent_pending = self.pending();
match parent_pending.subsurfaces.entry(self.unique_id) { match &mut parent_pending.state {
Entry::Occupied(mut o) => { None => parent_pending.state = Some(mem::take(&mut *pending)),
o.get_mut().state.merge(pending, &self.surface.client); Some(state) => state.merge(pending, &self.surface.client),
}
Entry::Vacant(v) => {
v.insert(CommittedSubsurface {
subsurface: self.clone(),
state: mem::take(&mut *pending),
});
}
} }
return CommitAction::AbortCommit; return CommitAction::AbortCommit;
} }
CommitAction::ContinueCommit CommitAction::ContinueCommit
} }
fn after_apply_commit(self: Rc<Self>, pending: &mut PendingState) { fn after_apply_commit(self: Rc<Self>) {
if let Some(pending) = &mut pending.subsurface {
if let Some(v) = pending.node.take() {
v.pending.set(false);
self.node.borrow_mut().replace(v);
}
if let Some((x, y)) = pending.position.take() {
self.position
.set(self.surface.buffer_abs_pos.get().at_point(x, y));
self.parent.need_extents_update.set(true);
}
}
let has_buffer = self.surface.buffer.is_some(); let has_buffer = self.surface.buffer.is_some();
if self.had_buffer.replace(has_buffer) != has_buffer { if self.had_buffer.replace(has_buffer) != has_buffer {
if has_buffer { if has_buffer {
@ -376,12 +389,16 @@ impl SurfaceExt for WlSubsurface {
surface: &WlSurface, surface: &WlSurface,
child: SubsurfaceId, child: SubsurfaceId,
consume: &mut dyn FnMut( consume: &mut dyn FnMut(
OccupiedEntry<SubsurfaceId, CommittedSubsurface>, OccupiedEntry<SubsurfaceId, AttachedSubsurfaceState>,
) -> Result<(), WlSurfaceError>, ) -> Result<(), WlSurfaceError>,
) -> Result<(), WlSurfaceError> { ) -> Result<(), WlSurfaceError> {
self.parent self.parent
.consume_pending_child(self.unique_id, |mut oe| { .consume_pending_child(self.unique_id, |mut oe| {
oe.get_mut().state.consume_child(child, &mut *consume) let oe = oe.get_mut();
match &mut oe.pending.state {
Some(state) => state.consume_child(child, &mut *consume),
_ => Ok(()),
}
})?; })?;
surface.pending.borrow_mut().consume_child(child, consume) surface.pending.borrow_mut().consume_child(child, consume)
} }

View file

@ -2,7 +2,7 @@ use {
crate::{ crate::{
ifs::wl_surface::{ ifs::wl_surface::{
x_surface::{xwayland_surface_v1::XwaylandSurfaceV1, xwindow::Xwindow}, x_surface::{xwayland_surface_v1::XwaylandSurfaceV1, xwindow::Xwindow},
PendingState, SurfaceExt, WlSurface, WlSurfaceError, SurfaceExt, WlSurface, WlSurfaceError,
}, },
leaks::Tracker, leaks::Tracker,
tree::ToplevelNode, tree::ToplevelNode,
@ -23,7 +23,7 @@ pub struct XSurface {
} }
impl SurfaceExt for XSurface { impl SurfaceExt for XSurface {
fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) { fn after_apply_commit(self: Rc<Self>) {
if let Some(xwindow) = self.xwindow.get() { if let Some(xwindow) = self.xwindow.get() {
xwindow.map_status_changed(); xwindow.map_status_changed();
} }

View file

@ -404,7 +404,7 @@ impl SurfaceExt for XdgSurface {
Ok(()) Ok(())
} }
fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) { fn after_apply_commit(self: Rc<Self>) {
if let Some(ext) = self.ext.get() { if let Some(ext) = self.ext.get() {
ext.post_commit(); ext.post_commit();
} }

View file

@ -349,7 +349,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
Ok(()) Ok(())
} }
fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) { fn after_apply_commit(self: Rc<Self>) {
let buffer_is_some = self.surface.buffer.is_some(); let buffer_is_some = self.surface.buffer.is_some();
let was_mapped = self.mapped.get(); let was_mapped = self.mapped.get();
if self.mapped.get() { if self.mapped.get() {

View file

@ -69,6 +69,7 @@ mod t0034_workspace_restoration;
mod t0035_scanout_feedback; mod t0035_scanout_feedback;
mod t0036_idle; mod t0036_idle;
mod t0037_toplevel_drag; mod t0037_toplevel_drag;
mod t0038_subsurface_parent_state;
pub trait TestCase: Sync { pub trait TestCase: Sync {
fn name(&self) -> &'static str; fn name(&self) -> &'static str;
@ -125,5 +126,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
t0035_scanout_feedback, t0035_scanout_feedback,
t0036_idle, t0036_idle,
t0037_toplevel_drag, t0037_toplevel_drag,
t0038_subsurface_parent_state,
} }
} }

View file

@ -0,0 +1,38 @@
use {
crate::{
it::{test_error::TestResult, testrun::TestRun},
theme::Color,
},
std::rc::Rc,
};
testcase!();
async fn test(run: Rc<TestRun>) -> TestResult {
let _ds = run.create_default_setup().await?;
let client = run.create_client().await?;
let win = client.create_window().await?;
win.set_color(255, 255, 255, 255);
win.map2().await?;
let ss = client.comp.create_surface().await?;
let vp = client.viewporter.get_viewport(&ss)?;
vp.set_destination(100, 100)?;
let buf = client.spbm.create_buffer(Color::SOLID_BLACK)?;
ss.attach(buf.id)?;
ss.commit()?;
let ss = client.sub.get_subsurface(ss.id, win.surface.id).await?;
ss.set_position(0, 0)?;
win.surface.commit()?;
client.compare_screenshot("1", false).await?;
ss.set_position(100, 100)?;
win.surface.commit()?;
client.compare_screenshot("2", false).await?;
Ok(())
}