@@ -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+
107116struct Popup {
108117 parent : Rc < XdgSurface > ,
109118 popup : Rc < XdgPopup > ,
@@ -209,8 +218,8 @@ impl PendingXdgSurfaceData {
209218}
210219
211220pub 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}
686734efrom ! ( XdgSurfaceError , WlSurfaceError ) ;
687735efrom ! ( XdgSurfaceError , ClientError ) ;
0 commit comments