1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-26 23:04:49 +03:00

more plumbing to route window events

This commit is contained in:
Wez Furlong 2018-03-01 21:33:49 -08:00
parent 44694fec95
commit 6e98b10027
6 changed files with 37 additions and 41 deletions

View File

@ -1,4 +1,5 @@
use failure::Error; use failure::Error;
use glium::glutin::WindowId;
mod none; mod none;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -27,7 +28,7 @@ pub enum Paste {
/// Abstracts away system specific clipboard implementation details. /// Abstracts away system specific clipboard implementation details.
pub trait ClipboardImpl { pub trait ClipboardImpl {
fn new(wakeup: Wakeup) -> Result<Self, Error> fn new(wakeup: Wakeup, window_id: WindowId) -> Result<Self, Error>
where where
Self: Sized; Self: Sized;
fn set_clipboard(&self, text: Option<String>) -> Result<(), Error>; fn set_clipboard(&self, text: Option<String>) -> Result<(), Error>;

View File

@ -1,5 +1,6 @@
use clipboard::{ClipboardImpl, Paste}; use clipboard::{ClipboardImpl, Paste};
use failure::Error; use failure::Error;
use glium::glutin::WindowId;
use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::mpsc::{channel, Receiver, Sender};
use wakeup::Wakeup; use wakeup::Wakeup;
@ -11,7 +12,7 @@ pub struct NoClipboard {
} }
impl ClipboardImpl for NoClipboard { impl ClipboardImpl for NoClipboard {
fn new(_wakeup: Wakeup) -> Result<Self, Error> { fn new(_wakeup: Wakeup, _window_id: WindowId) -> Result<Self, Error> {
let (sender, receiver) = channel(); let (sender, receiver) = channel();
Ok(Self { sender, receiver }) Ok(Self { sender, receiver })
} }

View File

@ -2,6 +2,7 @@
//! Check out https://tronche.com/gui/x/icccm/sec-2.html for some deep and complex //! Check out https://tronche.com/gui/x/icccm/sec-2.html for some deep and complex
//! background on what's happening in here. //! background on what's happening in here.
use failure::{self, Error}; use failure::{self, Error};
use glium::glutin::WindowId;
use mio::{Events, Poll, PollOpt, Ready, Token}; use mio::{Events, Poll, PollOpt, Ready, Token};
use mio::unix::EventedFd; use mio::unix::EventedFd;
use mio_extras::channel::{channel as mio_channel, Receiver as MioReceiver, Sender as MioSender}; use mio_extras::channel::{channel as mio_channel, Receiver as MioReceiver, Sender as MioSender};
@ -38,6 +39,7 @@ struct Inner {
atom_targets: xcb::Atom, atom_targets: xcb::Atom,
atom_clipboard: xcb::Atom, atom_clipboard: xcb::Atom,
wakeup: Wakeup, wakeup: Wakeup,
wakeup_window_id: WindowId,
} }
impl Inner { impl Inner {
@ -45,6 +47,7 @@ impl Inner {
receiver: MioReceiver<ClipRequest>, receiver: MioReceiver<ClipRequest>,
sender: Sender<Paste>, sender: Sender<Paste>,
wakeup: Wakeup, wakeup: Wakeup,
wakeup_window_id: WindowId,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let (conn, screen) = xcb::Connection::connect(None)?; let (conn, screen) = xcb::Connection::connect(None)?;
@ -99,17 +102,18 @@ impl Inner {
atom_targets, atom_targets,
atom_clipboard, atom_clipboard,
wakeup, wakeup,
wakeup_window_id,
}) })
} }
fn send(&mut self, packet: Paste) -> Result<(), Error> { fn send(&mut self, packet: Paste) -> Result<(), Error> {
match self.sender.send(packet) { match self.sender.send(packet) {
Ok(_) => { Ok(_) => {
self.wakeup.send(WakeupMsg::Paste)?; self.wakeup.send(WakeupMsg::Paste(self.wakeup_window_id))?;
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
self.wakeup.send(WakeupMsg::Paste)?; self.wakeup.send(WakeupMsg::Paste(self.wakeup_window_id))?;
bail!("clipboard: error sending to channel: {:?}", err); bail!("clipboard: error sending to channel: {:?}", err);
} }
} }
@ -390,11 +394,11 @@ pub struct Clipboard {
impl ClipboardImpl for Clipboard { impl ClipboardImpl for Clipboard {
/// Create a new clipboard instance. `ping` is /// Create a new clipboard instance. `ping` is
fn new(wakeup: Wakeup) -> Result<Self, Error> { fn new(wakeup: Wakeup, window_id: WindowId) -> Result<Self, Error> {
let (sender_clip, receiver_clip) = mio_channel(); let (sender_clip, receiver_clip) = mio_channel();
let (sender_paste, receiver_paste) = channel(); let (sender_paste, receiver_paste) = channel();
let clip_thread = thread::spawn(move || { let clip_thread = thread::spawn(move || {
match Inner::new(receiver_clip, sender_paste, wakeup) { match Inner::new(receiver_clip, sender_paste, wakeup, window_id) {
Ok(mut clip) => clip.clip_thread(), Ok(mut clip) => clip.clip_thread(),
Err(err) => eprintln!("failed to init clipboard window: {:?}", err), Err(err) => eprintln!("failed to init clipboard window: {:?}", err),
} }

View File

@ -14,13 +14,12 @@ use std::io::{Read, Write};
use std::process::Child; use std::process::Child;
use std::process::Command; use std::process::Command;
use std::rc::Rc; use std::rc::Rc;
use std::sync::mpsc::Receiver;
use term::{self, Terminal}; use term::{self, Terminal};
use term::{MouseButton, MouseEventKind}; use term::{MouseButton, MouseEventKind};
use term::KeyCode; use term::KeyCode;
use term::KeyModifiers; use term::KeyModifiers;
use term::hyperlink::Hyperlink; use term::hyperlink::Hyperlink;
use wakeup::{Wakeup, WakeupMsg}; use wakeup::Wakeup;
struct Host { struct Host {
display: glium::Display, display: glium::Display,
@ -65,7 +64,6 @@ pub struct TerminalWindow {
process: Child, process: Child,
last_mouse_coords: (f64, f64), last_mouse_coords: (f64, f64),
last_modifiers: KeyModifiers, last_modifiers: KeyModifiers,
wakeup_receiver: Receiver<WakeupMsg>,
window_position: Option<(i32, i32)>, window_position: Option<(i32, i32)>,
/// is is_some, holds position to be restored after exiting /// is is_some, holds position to be restored after exiting
/// fullscreen mode. /// fullscreen mode.
@ -76,7 +74,6 @@ impl TerminalWindow {
pub fn new( pub fn new(
event_loop: &glutin::EventsLoop, event_loop: &glutin::EventsLoop,
wakeup: Wakeup, wakeup: Wakeup,
wakeup_receiver: Receiver<WakeupMsg>,
width: u16, width: u16,
height: u16, height: u16,
terminal: Terminal, terminal: Terminal,
@ -102,11 +99,12 @@ impl TerminalWindow {
.with_srgb(true); .with_srgb(true);
let display = let display =
glium::Display::new(window, context, &event_loop).map_err(|e| format_err!("{:?}", e))?; glium::Display::new(window, context, &event_loop).map_err(|e| format_err!("{:?}", e))?;
let window_id = display.gl_window().id();
let host = Host { let host = Host {
display, display,
pty, pty,
clipboard: Clipboard::new(wakeup)?, clipboard: Clipboard::new(wakeup, window_id)?,
}; };
host.display.gl_window().set_cursor(MouseCursor::Text); host.display.gl_window().set_cursor(MouseCursor::Text);
@ -127,7 +125,6 @@ impl TerminalWindow {
process, process,
last_mouse_coords: (0.0, 0.0), last_mouse_coords: (0.0, 0.0),
last_modifiers: Default::default(), last_modifiers: Default::default(),
wakeup_receiver,
window_position, window_position,
is_fullscreen: None, is_fullscreen: None,
}) })
@ -561,26 +558,12 @@ impl TerminalWindow {
} => { } => {
self.paint()?; self.paint()?;
} }
Event::Awakened => 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()?;
},
Ok(WakeupMsg::Paste) => self.process_clipboard()?,
Err(_) => break,
}
},
Event::Suspended(suspended) => {
eprintln!("Suspended {:?}", suspended);
}
_ => {} _ => {}
} }
Ok(()) Ok(())
} }
fn process_clipboard(&mut self) -> Result<(), Error> { pub fn process_clipboard(&mut self) -> Result<(), Error> {
match self.host.clipboard.try_get_paste() { match self.host.clipboard.try_get_paste() {
Ok(Some(Paste::Cleared)) => { Ok(Some(Paste::Cleared)) => {
self.terminal.clear_selection(); self.terminal.clear_selection();

View File

@ -101,7 +101,6 @@ fn run_glium(
let window = gliumwindows::TerminalWindow::new( let window = gliumwindows::TerminalWindow::new(
&events_loop, &events_loop,
wakeup.clone(), wakeup.clone(),
wakeup_receiver,
initial_pixel_width, initial_pixel_width,
initial_pixel_height, initial_pixel_height,
terminal, terminal,
@ -154,7 +153,7 @@ fn run_glium(
Ok(_) => for event in &events { Ok(_) => for event in &events {
if event.token() == Token(0) && event.readiness().is_readable() { if event.token() == Token(0) && event.readiness().is_readable() {
wakeup wakeup
.send(WakeupMsg::PtyReadable) .send(WakeupMsg::PtyReadable(window_id))
.expect("failed to wakeup gui thread"); .expect("failed to wakeup gui thread");
} }
}, },
@ -181,15 +180,23 @@ fn run_glium(
glium::glutin::ControlFlow::Continue glium::glutin::ControlFlow::Continue
} }
}, },
Event::Awakened => match windows_by_id Event::Awakened => loop {
.get_mut(&window_id) match wakeup_receiver.try_recv() {
.unwrap() Ok(WakeupMsg::PtyReadable(window_id)) => {
.dispatch_event(event) windows_by_id.get_mut(&window_id).map(|w| w.try_read_pty());
{ }
Ok(_) => glium::glutin::ControlFlow::Continue, Ok(WakeupMsg::SigChld) => for (_, window) in windows_by_id.iter_mut() {
Err(err) => { window.test_for_child_exit().unwrap();
eprintln!("{:?}", err); },
glium::glutin::ControlFlow::Break Ok(WakeupMsg::Paint) => for (_, window) in windows_by_id.iter_mut() {
window.paint_if_needed().unwrap();
},
Ok(WakeupMsg::Paste(window_id)) => {
windows_by_id
.get_mut(&window_id)
.map(|w| w.process_clipboard());
}
Err(_) => return glium::glutin::ControlFlow::Continue,
} }
}, },
_ => glium::glutin::ControlFlow::Continue, _ => glium::glutin::ControlFlow::Continue,

View File

@ -1,13 +1,13 @@
use failure::Error; use failure::Error;
use glium::glutin::EventsLoopProxy; use glium::glutin::{EventsLoopProxy, WindowId};
use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::mpsc::{channel, Receiver, Sender};
#[derive(Debug)] #[derive(Debug)]
pub enum WakeupMsg { pub enum WakeupMsg {
PtyReadable, PtyReadable(WindowId),
SigChld, SigChld,
Paint, Paint,
Paste, Paste(WindowId),
} }
#[derive(Clone)] #[derive(Clone)]