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:
parent
44694fec95
commit
6e98b10027
@ -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>;
|
||||||
|
@ -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 })
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
29
src/main.rs
29
src/main.rs
@ -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,
|
||||||
|
@ -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)]
|
||||||
|
Loading…
Reference in New Issue
Block a user