@@ -50,10 +50,31 @@ use crate::utils::Serial;
50
50
51
51
use super :: { tree:: PrivateSurfaceData , CompositorHandler } ;
52
52
53
+ /// Kind for a [`Blocker`]
54
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
55
+ pub enum BlockerKind {
56
+ /// A immediate blocker which needs to be cleared before all delayed blockers.
57
+ Immediate ,
58
+ /// Defines a delayed blocker which will be evaluated after
59
+ /// all immediate blockers are cleared.
60
+ Delayed ,
61
+ }
62
+
53
63
/// Types potentially blocking state changes
54
64
pub trait Blocker {
55
65
/// Retrieve the current state of the blocker
56
66
fn state ( & self ) -> BlockerState ;
67
+
68
+ /// Retrieve the kind of the blocker
69
+ fn kind ( & self ) -> BlockerKind {
70
+ BlockerKind :: Immediate
71
+ }
72
+
73
+ /// Notifies the blocker that all immediate blockers have been cleared
74
+ /// for a particular surface
75
+ fn notify ( & self , surface : & WlSurface ) {
76
+ let _ = surface;
77
+ }
57
78
}
58
79
59
80
/// States of a [`Blocker`]
@@ -241,7 +262,7 @@ impl Transaction {
241
262
/// - if at least one blocker is cancelled, the transaction is cancelled
242
263
/// - otherwise, if at least one blocker is pending, the transaction is pending
243
264
/// - otherwise, all blockers are released, and the transaction is also released
244
- pub ( crate ) fn state ( & self ) -> BlockerState {
265
+ pub ( crate ) fn state ( & self , kind : Option < BlockerKind > ) -> BlockerState {
245
266
// In case all of our surfaces have been destroyed we can cancel this transaction
246
267
// as we won't apply its state anyway
247
268
if !self . surfaces . iter ( ) . any ( |surface| surface. 0 . is_alive ( ) ) {
@@ -251,13 +272,26 @@ impl Transaction {
251
272
use BlockerState :: * ;
252
273
self . blockers
253
274
. iter ( )
275
+ . filter ( |blocker| kind. map ( |kind| kind == blocker. kind ( ) ) . unwrap_or ( true ) )
254
276
. fold ( Released , |acc, blocker| match ( acc, blocker. state ( ) ) {
255
277
( Cancelled , _) | ( _, Cancelled ) => Cancelled ,
256
278
( Pending , _) | ( _, Pending ) => Pending ,
257
279
( Released , Released ) => Released ,
258
280
} )
259
281
}
260
282
283
+ pub ( crate ) fn notify_blockers ( & self ) {
284
+ for ( s, _) in & self . surfaces {
285
+ let Ok ( surface) = s. upgrade ( ) else {
286
+ continue ;
287
+ } ;
288
+
289
+ for blocker in self . blockers . iter ( ) {
290
+ blocker. notify ( & surface) ;
291
+ }
292
+ }
293
+ }
294
+
261
295
pub ( crate ) fn apply < C : CompositorHandler + ' static > ( self , dh : & DisplayHandle , state : & mut C ) {
262
296
for ( surface, id) in self . surfaces {
263
297
let Ok ( surface) = surface. upgrade ( ) else {
@@ -304,7 +338,7 @@ impl TransactionQueue {
304
338
while i < self . transactions . len ( ) {
305
339
let mut skip = false ;
306
340
// does the transaction have any active blocker?
307
- match self . transactions [ i] . state ( ) {
341
+ match self . transactions [ i] . state ( Some ( BlockerKind :: Immediate ) ) {
308
342
BlockerState :: Cancelled => {
309
343
// this transaction is cancelled, remove it without further processing
310
344
self . transactions . remove ( i) ;
@@ -342,7 +376,30 @@ impl TransactionQueue {
342
376
i += 1 ;
343
377
} else {
344
378
// this transaction is to be applied, yay!
345
- ready_transactions. push ( self . transactions . remove ( i) ) ;
379
+ let transaction = & mut self . transactions [ i] ;
380
+
381
+ transaction. notify_blockers ( ) ;
382
+
383
+ match transaction. state ( None ) {
384
+ BlockerState :: Pending => {
385
+ // this transaction is not yet ready and should be skipped, add its surfaces to our
386
+ // seen list
387
+ for ( s, _) in & transaction. surfaces {
388
+ // TODO: is this alive check still needed?
389
+ if !s. is_alive ( ) {
390
+ continue ;
391
+ }
392
+ self . seen_surfaces . insert ( s. id ( ) . protocol_id ( ) ) ;
393
+ }
394
+ i += 1 ;
395
+ }
396
+ BlockerState :: Released => ready_transactions. push ( self . transactions . remove ( i) ) ,
397
+ BlockerState :: Cancelled =>
398
+ // this transaction is cancelled, remove it without further processing
399
+ {
400
+ self . transactions . remove ( i) ;
401
+ }
402
+ }
346
403
}
347
404
}
348
405
0 commit comments