aboutsummaryrefslogtreecommitdiff
path: root/src/event_loop.rs
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2017-07-02 13:11:00 -0700
committerJoe Wilm <jwilm@users.noreply.github.com>2017-07-31 12:57:17 -0700
commit702df40da4ea8585ddfa129cd240c54bab6e42d7 (patch)
treee543dc617e3ea99029a019459922fe7d8bc50242 /src/event_loop.rs
parent9b13e344f0be068982845694442489e4932ccd5d (diff)
downloadalacritty-702df40da4ea8585ddfa129cd240c54bab6e42d7.tar.gz
alacritty-702df40da4ea8585ddfa129cd240c54bab6e42d7.zip
Read more from pty
Resolves an issue with partial draws where programs like vim would send data, but only part of it would be drawn. The logic for escaping when a write is pending has been removed in favor of limiting bytes processed during a pty_read call. The value of MAX_READ may not be ideal.
Diffstat (limited to 'src/event_loop.rs')
-rw-r--r--src/event_loop.rs70
1 files changed, 35 insertions, 35 deletions
diff --git a/src/event_loop.rs b/src/event_loop.rs
index c744dda0..56d8b992 100644
--- a/src/event_loop.rs
+++ b/src/event_loop.rs
@@ -64,13 +64,6 @@ impl DrainResult {
_ => false
}
}
-
- pub fn is_empty(&self) -> bool {
- match *self {
- DrainResult::Empty => true,
- _ => false
- }
- }
}
/// All of the mutable state needed to run the event loop
@@ -256,55 +249,62 @@ impl<Io> EventLoop<Io>
) -> io::Result<()>
where W: Write
{
+ const MAX_READ: usize = 65_536;
+ let mut processed = 0;
+ let mut terminal = None;
+
loop {
match self.pty.read(&mut buf[..]) {
Ok(0) => break,
Ok(got) => {
+ // Record bytes read; used to limit time spent in pty_read.
+ processed += got;
+
+ // Send a copy of bytes read to a subscriber. Used for
+ // example with ref test recording.
writer = writer.map(|w| {
- w.write_all(&buf[..got]).unwrap(); w
+ w.write_all(&buf[..got]).unwrap();
+ w
});
- let mut terminal = self.terminal.lock();
+ // Get reference to terminal. Lock is acquired on initial
+ // iteration and held until there's no bytes left to parse
+ // or we've reached MAX_READ.
+ if terminal.is_none() {
+ terminal = Some(self.terminal.lock());
+ }
+ let terminal = terminal.as_mut().unwrap();
+
+ // Run the parser
for byte in &buf[..got] {
- state.parser.advance(&mut *terminal, *byte, &mut self.pty);
+ state.parser.advance(&mut **terminal, *byte, &mut self.pty);
}
- // Only request a draw if one hasn't already been requested.
- //
- // This is a performance optimization even if only for X11
- // which is very expensive to hammer on the even loop wakeup
- if !terminal.dirty {
- self.display.notify();
- terminal.dirty = true;
-
- // Break for writing
- //
- // Want to prevent case where reading always returns
- // data and sequences like `C-c` cannot be sent.
- //
- // Doing this check in !terminal.dirty will prevent the
- // condition from being checked overzealously.
- //
- // Break if `drain_recv_channel` signals there is work to do or
- // shutting down.
- if state.writing.is_some()
- || !state.write_list.is_empty()
- || !self.drain_recv_channel(state).is_empty()
- {
- break;
- }
+ // Exit if we've processed enough bytes
+ if processed > MAX_READ {
+ break;
}
},
Err(err) => {
match err.kind() {
ErrorKind::Interrupted |
- ErrorKind::WouldBlock => break,
+ ErrorKind::WouldBlock => {
+ break;
+ },
_ => return Err(err),
}
}
}
}
+ // Only request a draw if one hasn't already been requested.
+ if let Some(mut terminal) = terminal {
+ if !terminal.dirty {
+ self.display.notify();
+ terminal.dirty = true;
+ }
+ }
+
Ok(())
}