@@ -99,10 +99,6 @@ pub struct TerminalSnapshot {
99
99
pub struct PendingUpdate {
100
100
/// Whether there's any pending update that needs rendering
101
101
dirty : bool ,
102
- /// The terminal snapshot with accumulated damage (primarily for synchronized updates)
103
- snapshot : Option < TerminalSnapshot > ,
104
- /// Whether this update came from a Wakeup event (needs damage check at render time)
105
- wakeup : bool ,
106
102
}
107
103
108
104
impl PendingUpdate {
@@ -116,177 +112,37 @@ impl PendingUpdate {
116
112
/// This is used by Wakeup events to defer damage calculation
117
113
pub fn mark_for_damage_check ( & mut self ) {
118
114
self . dirty = true ;
119
- self . wakeup = true ;
120
- // Don't create a snapshot yet - let the renderer do it when needed
121
115
}
122
116
123
- /// Clear the dirty flag without taking the snapshot
124
- /// Used when we manually process the damage in the renderer
117
+ /// Clear the dirty flag
125
118
pub fn clear_dirty ( & mut self ) {
126
119
self . dirty = false ;
127
- self . wakeup = false ;
128
120
}
129
121
130
- /// Mark as needing update with the given damage.
131
- ///
132
- /// For synchronized updates, this creates a snapshot immediately to capture the
133
- /// terminal state at the time of damage. For wakeup-based updates, this just
134
- /// marks as dirty and defers the actual damage check to render time to avoid
135
- /// lock contention.
122
+ /// Mark as needing update.
123
+ /// The actual snapshot will be computed at render time.
136
124
pub fn invalidate < U : rio_backend:: event:: EventListener > (
137
125
& mut self ,
138
- damage : TerminalDamage ,
139
- terminal : & FairMutex < Crosswords < U > > ,
126
+ _damage : TerminalDamage ,
127
+ _terminal : & FairMutex < Crosswords < U > > ,
140
128
) {
141
129
self . dirty = true ;
142
-
143
- // If we're in wakeup mode, skip the snapshot creation to avoid lock contention
144
- // The damage will be retrieved at render time instead
145
- if self . wakeup {
146
- // Keep the wakeup flag set - damage will be checked at render time
147
- return ;
148
- }
149
-
150
- // let lock_start = std::time::Instant::now();
151
- let mut terminal = terminal. lock ( ) ;
152
- // let lock_duration = lock_start.elapsed();
153
- // if lock_duration > std::time::Duration::from_millis(5) {
154
- // tracing::warn!("PendingUpdate::invalidate: Lock acquisition took {:?}", lock_duration);
155
- // }
156
-
157
- // match &damage {
158
- // TerminalDamage::Full => tracing::trace!("PendingUpdate: Full damage"),
159
- // TerminalDamage::Partial(ranges) => tracing::trace!("PendingUpdate: {} partial ranges damaged", ranges.len()),
160
- // TerminalDamage::CursorOnly => tracing::trace!("PendingUpdate: Cursor-only damage"),
161
- // }
162
-
163
- // Get the terminal's current damage
164
- let terminal_damage = terminal. peek_damage_event ( ) ;
165
-
166
- // Create or update the snapshot
167
- match & mut self . snapshot {
168
- None => {
169
- // Create new snapshot with merged terminal and incoming damage
170
- let initial_damage = match ( terminal_damage, & damage) {
171
- ( None , damage) => damage. clone ( ) ,
172
- ( Some ( term_damage) , damage) => {
173
- Self :: merge_damages ( & term_damage, damage)
174
- }
175
- } ;
176
-
177
- self . snapshot = Some ( TerminalSnapshot {
178
- colors : terminal. colors ,
179
- display_offset : terminal. display_offset ( ) ,
180
- blinking_cursor : terminal. blinking_cursor ,
181
- visible_rows : terminal. visible_rows ( ) ,
182
- cursor : terminal. cursor ( ) ,
183
- damage : initial_damage,
184
- columns : terminal. columns ( ) ,
185
- screen_lines : terminal. screen_lines ( ) ,
186
- } ) ;
187
- }
188
- Some ( existing_snapshot) => {
189
- // Update existing snapshot with fresh terminal state
190
- existing_snapshot. colors = terminal. colors ;
191
- existing_snapshot. display_offset = terminal. display_offset ( ) ;
192
- existing_snapshot. blinking_cursor = terminal. blinking_cursor ;
193
- existing_snapshot. visible_rows = terminal. visible_rows ( ) ;
194
- existing_snapshot. cursor = terminal. cursor ( ) ;
195
- existing_snapshot. columns = terminal. columns ( ) ;
196
- existing_snapshot. screen_lines = terminal. screen_lines ( ) ;
197
-
198
- // Merge existing snapshot damage with incoming damage
199
- existing_snapshot. damage =
200
- Self :: merge_damages ( & existing_snapshot. damage , & damage) ;
201
-
202
- // Also merge with terminal damage if present
203
- if let Some ( term_damage) = terminal_damage {
204
- existing_snapshot. damage =
205
- Self :: merge_damages ( & existing_snapshot. damage , & term_damage) ;
206
- }
207
- }
208
- }
209
-
210
- // Reset terminal damage since we've captured it in the snapshot
211
- terminal. reset_damage ( ) ;
212
-
213
- // Log final damage state only for significant updates
214
- if let Some ( ref snapshot) = self . snapshot {
215
- match & snapshot. damage {
216
- TerminalDamage :: Full => {
217
- tracing:: trace!( "PendingUpdate: Snapshot has full damage" )
218
- }
219
- TerminalDamage :: Partial ( ranges) if ranges. len ( ) > 50 => {
220
- tracing:: debug!(
221
- "PendingUpdate: Large snapshot with {} damaged ranges" ,
222
- ranges. len( )
223
- ) ;
224
- }
225
- TerminalDamage :: Partial ( ranges) if ranges. len ( ) > 10 => {
226
- tracing:: trace!(
227
- "PendingUpdate: Snapshot has {} damaged ranges" ,
228
- ranges. len( )
229
- ) ;
230
- }
231
- _ => { }
232
- }
233
- }
234
130
}
235
131
236
132
/// Mark as needing full update
237
133
pub fn invalidate_full < U : rio_backend:: event:: EventListener > (
238
134
& mut self ,
239
- terminal : & FairMutex < Crosswords < U > > ,
135
+ _terminal : & FairMutex < Crosswords < U > > ,
240
136
) {
241
- // If we're in wakeup mode, just mark as dirty
242
- if self . wakeup {
243
- self . dirty = true ;
244
- return ;
245
- }
246
- self . invalidate ( TerminalDamage :: Full , terminal) ;
137
+ self . dirty = true ;
247
138
}
248
139
249
- /// Take the snapshot and reset dirty flag
250
- /// This should only be called when actually rendering!
251
- pub fn take_snapshot ( & mut self ) -> ( Option < TerminalSnapshot > , bool ) {
252
- let was_wakeup = self . wakeup ;
140
+ /// Reset the dirty flag after rendering
141
+ pub fn reset ( & mut self ) {
253
142
self . dirty = false ;
254
- self . wakeup = false ;
255
- ( self . snapshot . take ( ) , was_wakeup)
256
143
}
257
144
258
- /// Merge two damages into one - this is critical for correctness
259
- fn merge_damages ( existing : & TerminalDamage , new : & TerminalDamage ) -> TerminalDamage {
260
- use std:: collections:: BTreeSet ;
261
-
262
- match ( existing, new) {
263
- // Any damage + Full = Full
264
- ( _, TerminalDamage :: Full ) | ( TerminalDamage :: Full , _) => TerminalDamage :: Full ,
265
- // Partial damages: merge the line lists efficiently using BTreeSet
266
- ( TerminalDamage :: Partial ( lines1) , TerminalDamage :: Partial ( lines2) ) => {
267
- let mut line_set = BTreeSet :: new ( ) ;
268
-
269
- // Add all damaged lines from both sets
270
- for damage in lines1. iter ( ) . chain ( lines2. iter ( ) ) {
271
- if damage. damaged {
272
- line_set. insert ( * damage) ;
273
- }
274
- }
275
-
276
- TerminalDamage :: Partial ( line_set)
277
- }
278
- // CursorOnly damages need special handling
279
- ( TerminalDamage :: CursorOnly , TerminalDamage :: Partial ( lines) ) => {
280
- TerminalDamage :: Partial ( lines. clone ( ) )
281
- }
282
- ( TerminalDamage :: Partial ( lines) , TerminalDamage :: CursorOnly ) => {
283
- TerminalDamage :: Partial ( lines. clone ( ) )
284
- }
285
- ( TerminalDamage :: CursorOnly , TerminalDamage :: CursorOnly ) => {
286
- TerminalDamage :: CursorOnly
287
- }
288
- }
289
- }
145
+
290
146
}
291
147
292
148
#[ cfg( test) ]
0 commit comments