diff options
| author | Ayose <ayosec@gmail.com> | 2024-03-11 00:00:00 +0000 |
|---|---|---|
| committer | Ayose <ayosec@gmail.com> | 2024-03-11 00:00:00 +0000 |
| commit | ff0f64fe699d69c7683d8e77bd5459709c49419f (patch) | |
| tree | 2fad7b6cac294f70429e04f723d02d4ab4985f8a | |
| parent | 21c9138b2c70ce86d2e51b79b35041324cbd280a (diff) | |
| parent | 41d2f1df4509148a6f1ffb3de59c2389a3a93283 (diff) | |
| download | r-alacritty-ff0f64fe699d69c7683d8e77bd5459709c49419f.tar.gz r-alacritty-ff0f64fe699d69c7683d8e77bd5459709c49419f.tar.bz2 r-alacritty-ff0f64fe699d69c7683d8e77bd5459709c49419f.zip | |
Merge remote-tracking branch 'vendor/master' into graphics
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | Cargo.lock | 8 | ||||
| -rw-r--r-- | alacritty/Cargo.toml | 2 | ||||
| -rw-r--r-- | alacritty/src/event.rs | 2 | ||||
| -rw-r--r-- | alacritty_terminal/src/event.rs | 4 | ||||
| -rw-r--r-- | alacritty_terminal/src/event_loop.rs | 7 | ||||
| -rw-r--r-- | alacritty_terminal/src/term/mod.rs | 2 | ||||
| -rw-r--r-- | alacritty_terminal/src/tty/mod.rs | 4 | ||||
| -rw-r--r-- | alacritty_terminal/src/tty/unix.rs | 17 | ||||
| -rw-r--r-- | alacritty_terminal/src/tty/windows/child.rs | 46 | ||||
| -rw-r--r-- | alacritty_terminal/src/tty/windows/mod.rs | 6 |
11 files changed, 67 insertions, 33 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f19c399..f5361861 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -487,7 +487,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Performance of scrolling regions with offset from the bottom - Extra mouse buttons are no longer ignored on Wayland - Numpad arrow keys are now properly recognized on Wayland -- Compilation when targetting aarch64-apple-darwin +- Compilation when targeting aarch64-apple-darwin - Window not being completely opaque on Windows - Window being always on top during alt-tab on Windows - Cursor position not reported to apps when mouse is moved with button held outside of window @@ -1131,9 +1131,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -2288,9 +2288,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.29.12" +version = "0.29.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b042fd2f023ddd9713f02f8f89c62f5a32c18d104ac182b480a0e3e6cb8d37f7" +checksum = "a7a3db69ffbe53a9babec7804da7a90f21020fcce1f2f5e5291e2311245b993d" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index e8dd0b3d..d9013484 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -41,7 +41,7 @@ serde_yaml = "0.9.25" smallvec = { version = "1.13.1", features = ["serde"] } toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.29.12", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.29.14", default-features = false, features = ["rwh_05", "serde"] } [build-dependencies] gl_generator = "0.14.0" diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index e1ee20f8..4fa397ad 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1356,7 +1356,7 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { TerminalEvent::PtyWrite(text) => self.ctx.write_to_pty(text.into_bytes()), TerminalEvent::MouseCursorDirty => self.reset_mouse_cursor(), TerminalEvent::CursorBlinkingChange => self.ctx.update_cursor_blinking(), - TerminalEvent::Exit | TerminalEvent::Wakeup => (), + TerminalEvent::Exit | TerminalEvent::ChildExit(_) | TerminalEvent::Wakeup => (), }, #[cfg(unix)] EventType::IpcConfig(_) => (), diff --git a/alacritty_terminal/src/event.rs b/alacritty_terminal/src/event.rs index caa1e9d6..e17d41ea 100644 --- a/alacritty_terminal/src/event.rs +++ b/alacritty_terminal/src/event.rs @@ -52,6 +52,9 @@ pub enum Event { /// Shutdown request. Exit, + + /// Child process exited with an error code. + ChildExit(i32), } impl Debug for Event { @@ -69,6 +72,7 @@ impl Debug for Event { Event::Wakeup => write!(f, "Wakeup"), Event::Bell => write!(f, "Bell"), Event::Exit => write!(f, "Exit"), + Event::ChildExit(code) => write!(f, "ChildExit({code})"), } } } diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs index 42025b00..929c642d 100644 --- a/alacritty_terminal/src/event_loop.rs +++ b/alacritty_terminal/src/event_loop.rs @@ -259,7 +259,11 @@ where for event in events.iter() { match event.key { tty::PTY_CHILD_EVENT_TOKEN => { - if let Some(tty::ChildEvent::Exited) = self.pty.next_child_event() { + if let Some(tty::ChildEvent::Exited(code)) = self.pty.next_child_event() + { + if let Some(code) = code { + self.event_proxy.send_event(Event::ChildExit(code)); + } if self.hold { // With hold enabled, make sure the PTY is drained. let _ = self.pty_read(&mut state, &mut buf, pipe.as_mut()); @@ -267,7 +271,6 @@ where // Without hold, shutdown the terminal. self.terminal.lock().exit(); } - self.event_proxy.send_event(Event::Wakeup); break 'event_loop; } diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index f81e3cca..a7a0a65a 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -1331,7 +1331,7 @@ impl<T: EventListener> Handler for Term<T> { return; } - trace!("Attemting to pop {to_pop} keyboard modes from the stack"); + trace!("Attempting to pop {to_pop} keyboard modes from the stack"); let new_len = self.keyboard_mode_stack.len().saturating_sub(to_pop as usize); self.keyboard_mode_stack.truncate(new_len); diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index d1bb023c..35d227b8 100644 --- a/alacritty_terminal/src/tty/mod.rs +++ b/alacritty_terminal/src/tty/mod.rs @@ -67,8 +67,8 @@ pub trait EventedReadWrite { /// Events concerning TTY child processes. #[derive(Debug, PartialEq, Eq)] pub enum ChildEvent { - /// Indicates the child has exited. - Exited, + /// Indicates the child has exited, with an error code if available. + Exited(Option<i32>), } /// A pseudoterminal (or PTY). diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 2c06d54f..8ce04191 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -4,7 +4,6 @@ use std::ffi::CStr; use std::fs::File; use std::io::{Error, ErrorKind, Read, Result}; use std::mem::MaybeUninit; -use std::os::fd::OwnedFd; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::net::UnixStream; use std::os::unix::process::CommandExt; @@ -38,17 +37,6 @@ macro_rules! die { }} } -/// Get raw fds for master/slave ends of a new PTY. -fn make_pty(size: Winsize) -> Result<(OwnedFd, OwnedFd)> { - let mut window_size = size; - window_size.ws_xpixel = 0; - window_size.ws_ypixel = 0; - - let ends = openpty(None, Some(&window_size))?; - - Ok((ends.controller, ends.user)) -} - /// Really only needed on BSD, but should be fine elsewhere. fn set_controlling_terminal(fd: c_int) { let res = unsafe { @@ -194,7 +182,8 @@ fn default_shell_command(shell: &str, user: &str) -> Command { /// Create a new TTY and return a handle to interact with it. pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result<Pty> { - let (master, slave) = make_pty(window_size.to_winsize())?; + let pty = openpty(None, Some(&window_size.to_winsize()))?; + let (master, slave) = (pty.controller, pty.user); let master_fd = master.as_raw_fd(); let slave_fd = slave.as_raw_fd(); @@ -381,7 +370,7 @@ impl EventedPty for Pty { None }, Ok(None) => None, - Ok(_) => Some(ChildEvent::Exited), + Ok(exit_status) => Some(ChildEvent::Exited(exit_status.and_then(|s| s.code()))), } } } diff --git a/alacritty_terminal/src/tty/windows/child.rs b/alacritty_terminal/src/tty/windows/child.rs index 6bc9ed20..dc6b992c 100644 --- a/alacritty_terminal/src/tty/windows/child.rs +++ b/alacritty_terminal/src/tty/windows/child.rs @@ -1,15 +1,16 @@ use std::ffi::c_void; use std::io::Error; +use std::num::NonZeroU32; use std::sync::atomic::{AtomicPtr, Ordering}; use std::sync::{mpsc, Arc, Mutex}; use polling::os::iocp::{CompletionPacket, PollerIocpExt}; use polling::{Event, Poller}; -use windows_sys::Win32::Foundation::{BOOLEAN, HANDLE}; +use windows_sys::Win32::Foundation::{BOOLEAN, FALSE, HANDLE}; use windows_sys::Win32::System::Threading::{ - RegisterWaitForSingleObject, UnregisterWait, INFINITE, WT_EXECUTEINWAITTHREAD, - WT_EXECUTEONLYONCE, + GetExitCodeProcess, GetProcessId, RegisterWaitForSingleObject, UnregisterWait, INFINITE, + WT_EXECUTEINWAITTHREAD, WT_EXECUTEONLYONCE, }; use crate::tty::ChildEvent; @@ -22,6 +23,7 @@ struct Interest { struct ChildExitSender { sender: mpsc::Sender<ChildEvent>, interest: Arc<Mutex<Option<Interest>>>, + child_handle: AtomicPtr<c_void>, } /// WinAPI callback to run when child process exits. @@ -31,7 +33,13 @@ extern "system" fn child_exit_callback(ctx: *mut c_void, timed_out: BOOLEAN) { } let event_tx: Box<_> = unsafe { Box::from_raw(ctx as *mut ChildExitSender) }; - let _ = event_tx.sender.send(ChildEvent::Exited); + + let mut exit_code = 0_u32; + let child_handle = event_tx.child_handle.load(Ordering::Relaxed) as HANDLE; + let status = unsafe { GetExitCodeProcess(child_handle, &mut exit_code) }; + let exit_code = if status == FALSE { None } else { Some(exit_code as i32) }; + event_tx.sender.send(ChildEvent::Exited(exit_code)).ok(); + let interest = event_tx.interest.lock().unwrap(); if let Some(interest) = interest.as_ref() { interest.poller.post(CompletionPacket::new(interest.event)).ok(); @@ -42,6 +50,8 @@ pub struct ChildExitWatcher { wait_handle: AtomicPtr<c_void>, event_rx: mpsc::Receiver<ChildEvent>, interest: Arc<Mutex<Option<Interest>>>, + child_handle: HANDLE, + pid: Option<NonZeroU32>, } impl ChildExitWatcher { @@ -50,7 +60,11 @@ impl ChildExitWatcher { let mut wait_handle: HANDLE = 0; let interest = Arc::new(Mutex::new(None)); - let sender_ref = Box::new(ChildExitSender { sender: event_tx, interest: interest.clone() }); + let sender_ref = Box::new(ChildExitSender { + sender: event_tx, + interest: interest.clone(), + child_handle: AtomicPtr::from(child_handle as *mut c_void), + }); let success = unsafe { RegisterWaitForSingleObject( @@ -66,10 +80,13 @@ impl ChildExitWatcher { if success == 0 { Err(Error::last_os_error()) } else { + let pid = unsafe { NonZeroU32::new(GetProcessId(child_handle)) }; Ok(ChildExitWatcher { wait_handle: AtomicPtr::from(wait_handle as *mut c_void), event_rx, interest, + child_handle, + pid, }) } } @@ -85,6 +102,23 @@ impl ChildExitWatcher { pub fn deregister(&self) { *self.interest.lock().unwrap() = None; } + + /// Retrieve the process handle of the underlying child process. + /// + /// This function does **not** pass ownership of the raw handle to you, + /// and the handle is only guaranteed to be valid while the hosted application + /// has not yet been destroyed. + /// + /// If you terminate the process using this handle, the terminal will get a + /// timeout error, and the child watcher will emit an `Exited` event. + pub fn raw_handle(&self) -> HANDLE { + self.child_handle + } + + /// Retrieve the Process ID associated to the underlying child process. + pub fn pid(&self) -> Option<NonZeroU32> { + self.pid + } } impl Drop for ChildExitWatcher { @@ -122,6 +156,6 @@ mod tests { poller.wait(&mut events, Some(WAIT_TIMEOUT)).unwrap(); assert_eq!(events.iter().next().unwrap().key, PTY_CHILD_EVENT_TOKEN); // Verify that at least one `ChildEvent::Exited` was received. - assert_eq!(child_exit_watcher.event_rx().try_recv(), Ok(ChildEvent::Exited)); + assert_eq!(child_exit_watcher.event_rx().try_recv(), Ok(ChildEvent::Exited(Some(1)))); } } diff --git a/alacritty_terminal/src/tty/windows/mod.rs b/alacritty_terminal/src/tty/windows/mod.rs index cbd803f1..6af162c8 100644 --- a/alacritty_terminal/src/tty/windows/mod.rs +++ b/alacritty_terminal/src/tty/windows/mod.rs @@ -47,6 +47,10 @@ impl Pty { ) -> Self { Self { backend: backend.into(), conout: conout.into(), conin: conin.into(), child_watcher } } + + pub fn child_watcher(&self) -> &ChildExitWatcher { + &self.child_watcher + } } fn with_key(mut event: Event, key: usize) -> Event { @@ -111,7 +115,7 @@ impl EventedPty for Pty { match self.child_watcher.event_rx().try_recv() { Ok(ev) => Some(ev), Err(TryRecvError::Empty) => None, - Err(TryRecvError::Disconnected) => Some(ChildEvent::Exited), + Err(TryRecvError::Disconnected) => Some(ChildEvent::Exited(None)), } } } |