@@ -44,9 +44,9 @@ use std::{
44
44
sync:: { atomic:: AtomicBool , Arc , Mutex } ,
45
45
} ;
46
46
47
- use wayland_server:: { protocol:: wl_surface:: WlSurface , DisplayHandle , Resource } ;
47
+ use wayland_server:: { protocol:: wl_surface:: WlSurface , DisplayHandle , Resource , Weak } ;
48
48
49
- use crate :: { utils:: IsAlive , utils :: Serial } ;
49
+ use crate :: utils:: Serial ;
50
50
51
51
use super :: { tree:: PrivateSurfaceData , CompositorHandler } ;
52
52
@@ -110,7 +110,7 @@ impl Blocker for Barrier {
110
110
111
111
#[ derive( Default ) ]
112
112
struct TransactionState {
113
- surfaces : Vec < ( WlSurface , Serial ) > ,
113
+ surfaces : Vec < ( Weak < WlSurface > , Serial ) > ,
114
114
blockers : Vec < Box < dyn Blocker + Send > > ,
115
115
}
116
116
@@ -123,7 +123,7 @@ impl TransactionState {
123
123
}
124
124
} else {
125
125
// the surface is not in the list, insert it
126
- self . surfaces . push ( ( surface, id) ) ;
126
+ self . surfaces . push ( ( surface. downgrade ( ) , id) ) ;
127
127
}
128
128
}
129
129
}
@@ -196,7 +196,9 @@ impl PendingTransaction {
196
196
// fuse our surfaces into our new transaction state
197
197
self . with_inner_state ( |state| {
198
198
for ( surface, id) in my_state. surfaces {
199
- state. insert ( surface, id) ;
199
+ if let Ok ( surface) = surface. upgrade ( ) {
200
+ state. insert ( surface, id) ;
201
+ }
200
202
}
201
203
state. blockers . extend ( my_state. blockers ) ;
202
204
} ) ;
@@ -221,7 +223,7 @@ impl PendingTransaction {
221
223
222
224
#[ derive( Debug ) ]
223
225
pub ( crate ) struct Transaction {
224
- surfaces : Vec < ( WlSurface , Serial ) > ,
226
+ surfaces : Vec < ( Weak < WlSurface > , Serial ) > ,
225
227
blockers : Vec < Box < dyn Blocker + Send > > ,
226
228
}
227
229
@@ -240,6 +242,12 @@ impl Transaction {
240
242
/// - otherwise, if at least one blocker is pending, the transaction is pending
241
243
/// - otherwise, all blockers are released, and the transaction is also released
242
244
pub ( crate ) fn state ( & self ) -> BlockerState {
245
+ // In case all of our surfaces have been destroyed we can cancel this transaction
246
+ // as we won't apply its state anyway
247
+ if !self . surfaces . iter ( ) . any ( |surface| surface. 0 . is_alive ( ) ) {
248
+ return BlockerState :: Cancelled ;
249
+ }
250
+
243
251
use BlockerState :: * ;
244
252
self . blockers
245
253
. iter ( )
@@ -252,6 +260,10 @@ impl Transaction {
252
260
253
261
pub ( crate ) fn apply < C : CompositorHandler + ' static > ( self , dh : & DisplayHandle , state : & mut C ) {
254
262
for ( surface, id) in self . surfaces {
263
+ let Ok ( surface) = surface. upgrade ( ) else {
264
+ continue ;
265
+ } ;
266
+
255
267
PrivateSurfaceData :: with_states ( & surface, |states| {
256
268
states. cached_state . apply_state ( id, dh) ;
257
269
} ) ;
@@ -307,7 +319,7 @@ impl TransactionQueue {
307
319
if !skip {
308
320
for ( s, _) in & self . transactions [ i] . surfaces {
309
321
// TODO: is this alive check still needed?
310
- if !s. alive ( ) {
322
+ if !s. is_alive ( ) {
311
323
continue ;
312
324
}
313
325
if self . seen_surfaces . contains ( & s. id ( ) . protocol_id ( ) ) {
@@ -322,7 +334,7 @@ impl TransactionQueue {
322
334
// seen list
323
335
for ( s, _) in & self . transactions [ i] . surfaces {
324
336
// TODO: is this alive check still needed?
325
- if !s. alive ( ) {
337
+ if !s. is_alive ( ) {
326
338
continue ;
327
339
}
328
340
self . seen_surfaces . insert ( s. id ( ) . protocol_id ( ) ) ;
0 commit comments