mirror of
https://github.com/wez/wezterm.git
synced 2024-11-27 12:23:46 +03:00
provide a more targeted channel for wakeups
This allows using the mio poll timer as the signal for drawing frames, rather than always drawing them after each byte is read from the pty. We're using 50ms as the frame interval at the moment.
This commit is contained in:
parent
f6a95aafcf
commit
79ebf717e8
@ -13,12 +13,14 @@ use std::io::{Read, Write};
|
||||
use std::process::Child;
|
||||
use std::process::Command;
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::sync::mpsc::TryRecvError;
|
||||
use term::{self, Terminal};
|
||||
use term::{MouseButton, MouseEventKind};
|
||||
use term::KeyCode;
|
||||
use term::KeyModifiers;
|
||||
use term::hyperlink::Hyperlink;
|
||||
use wakeup::WakeupMsg;
|
||||
|
||||
struct Host {
|
||||
display: glium::Display,
|
||||
@ -62,11 +64,13 @@ pub struct TerminalWindow {
|
||||
terminal: Terminal,
|
||||
process: Child,
|
||||
last_mouse_coords: (f64, f64),
|
||||
wakeup_receiver: Receiver<WakeupMsg>,
|
||||
}
|
||||
|
||||
impl TerminalWindow {
|
||||
pub fn new(
|
||||
event_loop: &glutin::EventsLoop,
|
||||
wakeup_receiver: Receiver<WakeupMsg>,
|
||||
width: u16,
|
||||
height: u16,
|
||||
terminal: Terminal,
|
||||
@ -116,6 +120,7 @@ impl TerminalWindow {
|
||||
terminal,
|
||||
process,
|
||||
last_mouse_coords: (0.0, 0.0),
|
||||
wakeup_receiver,
|
||||
})
|
||||
}
|
||||
|
||||
@ -439,8 +444,19 @@ impl TerminalWindow {
|
||||
Err(TryRecvError::Disconnected) => bail!("clipboard thread died"),
|
||||
}
|
||||
|
||||
self.try_read_pty()?;
|
||||
self.test_for_child_exit()?;
|
||||
loop {
|
||||
match self.wakeup_receiver.try_recv() {
|
||||
Ok(WakeupMsg::PtyReadable) => self.try_read_pty()?,
|
||||
Ok(WakeupMsg::SigChld) => self.test_for_child_exit()?,
|
||||
Ok(WakeupMsg::Paint) => if self.terminal.has_dirty_lines() {
|
||||
self.paint()?;
|
||||
},
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::Suspended(suspended) => {
|
||||
eprintln!("Suspended {:?}", suspended);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
35
src/main.rs
35
src/main.rs
@ -38,12 +38,15 @@ use std::os::unix::io::AsRawFd;
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
mod config;
|
||||
|
||||
mod opengl;
|
||||
|
||||
mod clipboard;
|
||||
mod wakeup;
|
||||
use wakeup::{Wakeup, WakeupMsg};
|
||||
mod gliumwindows;
|
||||
|
||||
mod font;
|
||||
@ -81,12 +84,15 @@ fn run_glium(
|
||||
initial_pixel_height: u16,
|
||||
) -> Result<(), Error> {
|
||||
let mut events_loop = glium::glutin::EventsLoop::new();
|
||||
sigchld::activate(events_loop.create_proxy())?;
|
||||
|
||||
let (wakeup_receiver, wakeup) = Wakeup::new(events_loop.create_proxy());
|
||||
sigchld::activate(wakeup.clone())?;
|
||||
|
||||
let master_fd = master.as_raw_fd();
|
||||
|
||||
let mut window = gliumwindows::TerminalWindow::new(
|
||||
&events_loop,
|
||||
wakeup_receiver,
|
||||
initial_pixel_width,
|
||||
initial_pixel_height,
|
||||
terminal,
|
||||
@ -100,7 +106,7 @@ fn run_glium(
|
||||
)?;
|
||||
|
||||
{
|
||||
let proxy = events_loop.create_proxy();
|
||||
let mut wakeup = wakeup.clone();
|
||||
thread::spawn(move || {
|
||||
let poll = Poll::new().expect("mio Poll failed to init");
|
||||
poll.register(
|
||||
@ -112,12 +118,24 @@ fn run_glium(
|
||||
let mut events = Events::with_capacity(8);
|
||||
|
||||
loop {
|
||||
match poll.poll(&mut events, None) {
|
||||
Ok(_) => for event in &events {
|
||||
match poll.poll(&mut events, Some(Duration::from_millis(50))) {
|
||||
Ok(n) if n > 0 => for event in &events {
|
||||
if event.token() == Token(0) && event.readiness().is_readable() {
|
||||
proxy.wakeup().expect("failed to wake event loop");
|
||||
wakeup
|
||||
.send(WakeupMsg::PtyReadable)
|
||||
.expect("failed to wakeup gui thread");
|
||||
}
|
||||
},
|
||||
Ok(_) => {
|
||||
// Tick and wakeup the gui thread to ask it to render
|
||||
// if needed. Without this we'd only repaint when
|
||||
// the window system decides that we were damaged.
|
||||
// We don't want to paint after every state change
|
||||
// as that would be too frequent.
|
||||
wakeup
|
||||
.send(WakeupMsg::Paint)
|
||||
.expect("failed to wakeup gui thread");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -125,12 +143,7 @@ fn run_glium(
|
||||
}
|
||||
|
||||
events_loop.run_forever(|event| match window.dispatch_event(event) {
|
||||
Ok(_) => {
|
||||
if window.need_paint() {
|
||||
window.paint().expect("paint failed");
|
||||
}
|
||||
glium::glutin::ControlFlow::Continue
|
||||
}
|
||||
Ok(_) => glium::glutin::ControlFlow::Continue,
|
||||
Err(err) => {
|
||||
eprintln!("{:?}", err);
|
||||
glium::glutin::ControlFlow::Break
|
||||
|
@ -1,28 +1,28 @@
|
||||
//! Helper for detecting SIGCHLD
|
||||
|
||||
use failure::Error;
|
||||
use glium::glutin::EventsLoopProxy;
|
||||
use libc;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use wakeup::{Wakeup, WakeupMsg};
|
||||
|
||||
static mut EVENT_LOOP: Option<EventsLoopProxy> = None;
|
||||
static mut EVENT_LOOP: Option<Wakeup> = None;
|
||||
|
||||
extern "C" fn chld_handler(_signo: libc::c_int, _si: *const libc::siginfo_t, _: *const u8) {
|
||||
unsafe {
|
||||
match EVENT_LOOP.as_mut() {
|
||||
Some(proxy) => {
|
||||
proxy.wakeup().ok();
|
||||
Some(wakeup) => {
|
||||
wakeup.send(WakeupMsg::SigChld).ok();
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn activate(proxy: EventsLoopProxy) -> Result<(), Error> {
|
||||
pub fn activate(wakeup: Wakeup) -> Result<(), Error> {
|
||||
unsafe {
|
||||
EVENT_LOOP = Some(proxy);
|
||||
EVENT_LOOP = Some(wakeup);
|
||||
|
||||
let mut sa: libc::sigaction = mem::zeroed();
|
||||
sa.sa_sigaction = chld_handler as usize;
|
||||
|
28
src/wakeup.rs
Normal file
28
src/wakeup.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use failure::Error;
|
||||
use glium::glutin::EventsLoopProxy;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WakeupMsg {
|
||||
PtyReadable,
|
||||
SigChld,
|
||||
Paint,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Wakeup {
|
||||
sender: Sender<WakeupMsg>,
|
||||
proxy: EventsLoopProxy,
|
||||
}
|
||||
|
||||
impl Wakeup {
|
||||
pub fn new(proxy: EventsLoopProxy) -> (Receiver<WakeupMsg>, Self) {
|
||||
let (sender, receiver) = channel();
|
||||
(receiver, Self { sender, proxy })
|
||||
}
|
||||
pub fn send(&mut self, what: WakeupMsg) -> Result<(), Error> {
|
||||
self.sender.send(what)?;
|
||||
self.proxy.wakeup()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user