Skip to content

Commit 3a4ca4d

Browse files
authored
Merge pull request #689 from mahkoh/jorth/xdg-initial-commit-state
xdg-shell: make acked serial part of the pending state
2 parents c9f54cd + 17ac4ca commit 3a4ca4d

File tree

7 files changed

+85
-36
lines changed

7 files changed

+85
-36
lines changed

src/ifs/wl_surface.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ struct PendingState {
486486
commit_time: Option<u64>,
487487
tray_item_ack_serial: Option<u32>,
488488
color_description: Option<Option<Rc<ColorDescription>>>,
489+
serial: Option<u64>,
489490
}
490491

491492
struct AttachedSubsurfaceState {
@@ -539,6 +540,7 @@ impl PendingState {
539540
opt!(commit_time);
540541
opt!(tray_item_ack_serial);
541542
opt!(color_description);
543+
opt!(serial);
542544
{
543545
let (dx1, dy1) = self.offset;
544546
let (dx2, dy2) = mem::take(&mut next.offset);

src/ifs/wl_surface/xdg_surface.rs

Lines changed: 73 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ pub struct XdgSurface {
8787
base: Rc<XdgWmBase>,
8888
role: Cell<XdgSurfaceRole>,
8989
pub surface: Rc<WlSurface>,
90-
requested_serial: NumCell<u32>,
91-
acked_serial: Cell<Option<u32>>,
90+
requested_serial: NumCell<u64>,
91+
acked_serial: Cell<u64>,
92+
applied_serial: Cell<u64>,
9293
geometry: Cell<Option<Rect>>,
9394
extents: Cell<Rect>,
9495
effective_geometry: Cell<Rect>,
@@ -99,11 +100,19 @@ pub struct XdgSurface {
99100
popups: CopyHashMap<XdgPopupId, Rc<Popup>>,
100101
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
101102
pub tracker: Tracker<Self>,
102-
have_initial_commit: Cell<bool>,
103+
initial_commit_state: Cell<InitialCommitState>,
103104
configure_scheduled: Cell<bool>,
104105
destroyed: Cell<bool>,
105106
}
106107

108+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
109+
enum InitialCommitState {
110+
#[default]
111+
Unmapped,
112+
Sent,
113+
Mapped,
114+
}
115+
107116
struct Popup {
108117
parent: Rc<XdgSurface>,
109118
popup: Rc<XdgPopup>,
@@ -209,8 +218,8 @@ impl PendingXdgSurfaceData {
209218
}
210219

211220
pub trait XdgSurfaceExt: Debug {
212-
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
213-
Ok(())
221+
fn initial_configure(self: Rc<Self>) {
222+
// nothing
214223
}
215224

216225
fn post_commit(self: Rc<Self>) {
@@ -250,7 +259,8 @@ impl XdgSurface {
250259
role: Cell::new(XdgSurfaceRole::None),
251260
surface: surface.clone(),
252261
requested_serial: NumCell::new(1),
253-
acked_serial: Cell::new(None),
262+
acked_serial: Cell::new(0),
263+
applied_serial: Cell::new(0),
254264
geometry: Cell::new(None),
255265
extents: Cell::new(surface.extents.get()),
256266
effective_geometry: Default::default(),
@@ -261,7 +271,7 @@ impl XdgSurface {
261271
popups: Default::default(),
262272
workspace: Default::default(),
263273
tracker: Default::default(),
264-
have_initial_commit: Default::default(),
274+
initial_commit_state: Default::default(),
265275
configure_scheduled: Default::default(),
266276
destroyed: Default::default(),
267277
}
@@ -350,17 +360,34 @@ impl XdgSurface {
350360
if self.configure_scheduled.replace(true) {
351361
return;
352362
}
353-
let serial = self.requested_serial.add_fetch(1);
354363
self.surface
355364
.client
356365
.state
357366
.xdg_surface_configure_events
358367
.push(XdgSurfaceConfigureEvent {
359368
xdg: self.clone(),
360-
serial,
369+
serial: self.next_serial() as _,
361370
});
362371
}
363372

373+
fn next_serial(&self) -> u64 {
374+
let mut serial = self.requested_serial.add_fetch(1);
375+
if serial as u32 == 0 {
376+
serial = self.requested_serial.add_fetch(1);
377+
}
378+
serial
379+
}
380+
381+
fn map_serial(&self, serial: u32) -> u64 {
382+
let max = self.requested_serial.get();
383+
let mask = u32::MAX as u64;
384+
let mut serial = max & !mask | (serial as u64);
385+
if serial > max {
386+
serial = serial.saturating_sub(mask + 1);
387+
}
388+
serial
389+
}
390+
364391
pub fn send_configure(&self, serial: u32) {
365392
self.surface.client.event(Configure {
366393
self_id: self.id,
@@ -510,9 +537,13 @@ impl XdgSurfaceRequestHandler for XdgSurface {
510537
}
511538

512539
fn ack_configure(&self, req: AckConfigure, _slf: &Rc<Self>) -> Result<(), Self::Error> {
513-
if self.requested_serial.get() == req.serial {
514-
self.acked_serial.set(Some(req.serial));
540+
let serial = self.map_serial(req.serial);
541+
let last = self.acked_serial.get();
542+
if serial <= last {
543+
return Err(XdgSurfaceError::InvalidSerial(serial, last));
515544
}
545+
self.acked_serial.set(serial);
546+
self.surface.pending.borrow_mut().serial = Some(serial);
516547
Ok(())
517548
}
518549
}
@@ -616,26 +647,41 @@ impl SurfaceExt for XdgSurface {
616647
self: Rc<Self>,
617648
pending: &mut PendingState,
618649
) -> Result<(), WlSurfaceError> {
619-
if !self.have_initial_commit.get()
620-
&& let Some(ext) = self.ext.get()
621-
{
622-
ext.initial_configure()?;
623-
self.schedule_configure();
624-
self.have_initial_commit.set(true);
625-
}
626-
if let Some(pending) = &mut pending.xdg_surface
627-
&& let Some(geometry) = pending.geometry.take()
628-
{
629-
let prev = self.geometry.replace(Some(geometry));
630-
if prev != Some(geometry) {
631-
self.update_effective_geometry();
632-
self.update_extents();
650+
if let Some(pending) = &mut pending.xdg_surface {
651+
if let Some(geometry) = pending.geometry.take() {
652+
let prev = self.geometry.replace(Some(geometry));
653+
if prev != Some(geometry) {
654+
self.update_effective_geometry();
655+
self.update_extents();
656+
}
633657
}
634658
}
659+
if let Some(serial) = pending.serial.take() {
660+
self.applied_serial.set(serial);
661+
}
635662
Ok(())
636663
}
637664

638665
fn after_apply_commit(self: Rc<Self>) {
666+
match self.initial_commit_state.get() {
667+
InitialCommitState::Unmapped => {
668+
if let Some(ext) = self.ext.get() {
669+
ext.initial_configure();
670+
self.schedule_configure();
671+
self.initial_commit_state.set(InitialCommitState::Sent);
672+
}
673+
}
674+
InitialCommitState::Sent => {
675+
if self.surface.buffer.is_some() {
676+
self.initial_commit_state.set(InitialCommitState::Mapped);
677+
}
678+
}
679+
InitialCommitState::Mapped => {
680+
if self.surface.buffer.is_none() {
681+
self.initial_commit_state.set(InitialCommitState::Unmapped);
682+
}
683+
}
684+
}
639685
if let Some(ext) = self.ext.get() {
640686
ext.post_commit();
641687
}
@@ -682,6 +728,8 @@ pub enum XdgSurfaceError {
682728
AlreadyConstructed,
683729
#[error(transparent)]
684730
WlSurfaceError(Box<WlSurfaceError>),
731+
#[error("The serial {0} is not larger than the previously acked serial {1}")]
732+
InvalidSerial(u64, u64),
685733
}
686734
efrom!(XdgSurfaceError, WlSurfaceError);
687735
efrom!(XdgSurfaceError, ClientError);

src/ifs/wl_surface/xdg_surface/xdg_popup.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use {
77
wl_seat::{NodeSeatState, WlSeatGlobal, tablet::TabletTool},
88
wl_surface::{
99
tray::TrayItemId,
10-
xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt},
10+
xdg_surface::{XdgSurface, XdgSurfaceExt},
1111
},
1212
xdg_positioner::{
1313
CA_FLIP_X, CA_FLIP_Y, CA_RESIZE_X, CA_RESIZE_Y, CA_SLIDE_X, CA_SLIDE_Y,
@@ -417,13 +417,12 @@ impl StackedNode for XdgPopup {
417417
}
418418

419419
impl XdgSurfaceExt for XdgPopup {
420-
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
420+
fn initial_configure(self: Rc<Self>) {
421421
if let Some(parent) = self.parent.get() {
422422
self.update_position(&*parent);
423423
let rel = self.relative_position.get();
424424
self.send_configure(rel.x1(), rel.y1(), rel.width(), rel.height());
425425
}
426-
Ok(())
427426
}
428427

429428
fn post_commit(self: Rc<Self>) {

src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ use {
1313
wl_surface::{
1414
WlSurface,
1515
xdg_surface::{
16-
XdgSurface, XdgSurfaceError, XdgSurfaceExt,
17-
xdg_toplevel::xdg_dialog_v1::XdgDialogV1,
16+
XdgSurface, XdgSurfaceExt, xdg_toplevel::xdg_dialog_v1::XdgDialogV1,
1817
},
1918
},
2019
xdg_toplevel_drag_v1::XdgToplevelDragV1,
@@ -753,14 +752,13 @@ impl ToplevelNodeBase for XdgToplevel {
753752
}
754753

755754
impl XdgSurfaceExt for XdgToplevel {
756-
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
755+
fn initial_configure(self: Rc<Self>) {
757756
let rect = self.xdg.absolute_desired_extents.get();
758757
if rect.is_empty() {
759758
self.send_configure(0, 0);
760759
} else {
761760
self.send_configure_checked(rect.width(), rect.height());
762761
}
763-
Ok(())
764762
}
765763

766764
fn post_commit(self: Rc<Self>) {

src/it/test_ifs/test_xdg_base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl TestXdgWmBase {
5050
tran: self.tran.clone(),
5151
_server: server,
5252
destroyed: Cell::new(false),
53-
last_serial: Cell::new(0),
53+
last_serial: Default::default(),
5454
});
5555
self.tran.add_obj(xdg.clone())?;
5656
Ok(xdg)

src/it/test_ifs/test_xdg_surface.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct TestXdgSurface {
1919
pub tran: Rc<TestTransport>,
2020
pub _server: Rc<XdgSurface>,
2121
pub destroyed: Cell<bool>,
22-
pub last_serial: Cell<u32>,
22+
pub last_serial: Cell<Option<u32>>,
2323
}
2424

2525
impl TestXdgSurface {
@@ -63,7 +63,7 @@ impl TestXdgSurface {
6363

6464
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
6565
let ev = Configure::parse_full(parser)?;
66-
self.last_serial.set(ev.serial);
66+
self.last_serial.set(Some(ev.serial));
6767
Ok(())
6868
}
6969
}

src/it/test_utils/test_window.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ pub struct TestWindow {
1515

1616
impl TestWindow {
1717
pub async fn map(&self) -> Result<(), TestError> {
18-
self.xdg.ack_configure(self.xdg.last_serial.get())?;
18+
if let Some(serial) = self.xdg.last_serial.take() {
19+
self.xdg.ack_configure(serial)?;
20+
}
1921
self.surface
2022
.map(self.tl.core.width.get(), self.tl.core.height.get())
2123
.await?;

0 commit comments

Comments
 (0)