aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAyose <ayosec@gmail.com>2024-03-11 00:00:00 +0000
committerAyose <ayosec@gmail.com>2024-03-11 00:00:00 +0000
commitff0f64fe699d69c7683d8e77bd5459709c49419f (patch)
tree2fad7b6cac294f70429e04f723d02d4ab4985f8a
parent21c9138b2c70ce86d2e51b79b35041324cbd280a (diff)
parent41d2f1df4509148a6f1ffb3de59c2389a3a93283 (diff)
downloadr-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.md2
-rw-r--r--Cargo.lock8
-rw-r--r--alacritty/Cargo.toml2
-rw-r--r--alacritty/src/event.rs2
-rw-r--r--alacritty_terminal/src/event.rs4
-rw-r--r--alacritty_terminal/src/event_loop.rs7
-rw-r--r--alacritty_terminal/src/term/mod.rs2
-rw-r--r--alacritty_terminal/src/tty/mod.rs4
-rw-r--r--alacritty_terminal/src/tty/unix.rs17
-rw-r--r--alacritty_terminal/src/tty/windows/child.rs46
-rw-r--r--alacritty_terminal/src/tty/windows/mod.rs6
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
diff --git a/Cargo.lock b/Cargo.lock
index 78be55b2..59febe23 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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)),
}
}
}