From dfdefb2ed452eb46aa2098c1444d0f5d887dcbca Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sun, 17 Feb 2019 12:11:12 -0800 Subject: [PATCH] Now basically functional on windows! --- src/font/rtype.rs | 6 ++-- src/gliumwindows.rs | 8 +++-- src/opengl/render.rs | 8 ++--- src/winpty.rs | 70 +++++++++++++++++++++++++++++--------------- 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/font/rtype.rs b/src/font/rtype.rs index b5b1ce554..cd124ed3b 100644 --- a/src/font/rtype.rs +++ b/src/font/rtype.rs @@ -75,10 +75,6 @@ impl<'a> NamedFont for NamedFontImpl<'a> { let hmetrics = glyph.h_metrics(); let glyph = glyph.positioned(point(0.0, 0.0)); - if c != ' ' { - eprintln!("{} -> glyph {} {:?}", c, glyph.id().0, hmetrics); - } - shaped.push(GlyphInfo { #[cfg(debug_assertions)] text: s[cluster..cluster].to_string(), @@ -140,10 +136,12 @@ impl<'a> Font for NamedFontImpl<'a> { data.push(v); // green data.push(v); // blue }); + /* eprintln!( "rasterize_glyph {} {}x{} {} bounds {:?}", glyph_pos, width, height, self.cell_height, bounds ); + */ // FIXME: there's something funky about either the bearing // calculation here or the y_offset calculation in the // shape function that causes the baseline to vary and diff --git a/src/gliumwindows.rs b/src/gliumwindows.rs index 49f9aaba6..792252964 100644 --- a/src/gliumwindows.rs +++ b/src/gliumwindows.rs @@ -131,7 +131,7 @@ impl TerminalWindow { let display = { let pref_context = glutin::ContextBuilder::new() - .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (2, 0))) + //.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (2, 0))) .with_vsync(true) .with_pixel_format(24, 8) .with_srgb(true); @@ -143,7 +143,11 @@ impl TerminalWindow { match glium::Display::new(window, pref_context, &*mut_loop) { Ok(display) => display, - Err(_) => { + Err(err) => { + eprintln!( + "preferred GL context not available: {}, try a fallback", + err + ); // Take anything that might show something. // This fallback is typically hit when running with a remote // X server. diff --git a/src/opengl/render.rs b/src/opengl/render.rs index b14a44429..d25193983 100644 --- a/src/opengl/render.rs +++ b/src/opengl/render.rs @@ -110,7 +110,7 @@ implement_vertex!( ); const VERTEX_SHADER: &str = r#" -#version 300 es +#version 330 in vec2 position; in vec2 adjust; in vec2 tex; @@ -187,7 +187,7 @@ const U_STRIKE_ONE: f32 = 4.0 / U_COLS; const U_STRIKE_TWO: f32 = 5.0 / U_COLS; const FRAGMENT_SHADER: &str = r#" -#version 300 es +#version 330 precision mediump float; in vec2 tex_coords; in vec2 underline_coords; @@ -227,7 +227,7 @@ void main() { // take that pixel, otherwise we'll use the background color. if (o_underline != 0.0) { // Compute the pixel color for this location - vec4 under_color = multiply(o_fg_color, texture2D(underline_tex, underline_coords)); + vec4 under_color = multiply(o_fg_color, texture(underline_tex, underline_coords)); if (under_color.a != 0.0) { // if the line glyph isn't transparent in this position then // we take this pixel color, otherwise we'll leave the color @@ -236,7 +236,7 @@ void main() { } } } else { - color = texture2D(glyph_tex, tex_coords); + color = texture(glyph_tex, tex_coords); if (o_has_color == 0.0) { // if it's not a color emoji, tint with the fg_color color = multiply(o_fg_color, color); diff --git a/src/winpty.rs b/src/winpty.rs index 40ab5f496..deedc14ac 100644 --- a/src/winpty.rs +++ b/src/winpty.rs @@ -3,7 +3,6 @@ use std::io::{self, Error as IoError, Result as IoResult}; extern crate winapi; use std::env; use std::ffi::{OsStr, OsString}; -use std::fs; use std::mem; use std::os::windows::ffi::OsStrExt; use std::os::windows::ffi::OsStringExt; @@ -33,20 +32,20 @@ pub struct Command { impl Command { pub fn new>(program: S) -> Self { Self { - args: vec![Self::search_path(program.as_ref().to_owned())], + args: vec![program.as_ref().to_owned()], input: None, output: None, hpc: None, } } - fn search_path(exe: OsString) -> OsString { + fn search_path(exe: &OsStr) -> OsString { if let Some(path) = env::var_os("PATH") { let extensions = env::var_os("PATHEXT").unwrap_or(".EXE".into()); for path in env::split_paths(&path) { // Check for exactly the user's string in this path dir let candidate = path.join(&exe); - if fs::metadata(&candidate).is_ok() { + if candidate.exists() { return candidate.into_os_string(); } @@ -58,14 +57,14 @@ impl Command { // doesn't want that let ext = ext.to_str().expect("PATHEXT entries must be utf8"); let path = path.join(&exe).with_extension(&ext[1..]); - if fs::metadata(&path).is_ok() { + if path.exists() { return path.into_os_string(); } } } } - exe + exe.to_owned() } pub fn arg>(&mut self, arg: S) -> &mut Command { @@ -105,21 +104,23 @@ impl Command { self } - fn cmdline(&self) -> Result, Error> { + fn cmdline(&self) -> Result<(Vec, Vec), Error> { let mut cmdline = Vec::::new(); - for (idx, arg) in self.args.iter().enumerate() { - if idx != 0 { - cmdline.push(' ' as u16); - } + + let exe = Self::search_path(&self.args[0]); + Self::append_quoted(&exe, &mut cmdline); + let exe = exe.encode_wide().collect(); + + for arg in self.args.iter().skip(1) { + cmdline.push(' ' as u16); ensure!( !arg.encode_wide().any(|c| c == 0), - "invalid encoding for command line argument at index {}: {:?}", - idx, + "invalid encoding for command line argument {:?}", arg ); Self::append_quoted(arg, &mut cmdline); } - Ok(cmdline) + Ok((exe, cmdline)) } // Borrowed from https://github.com/hniksic/rust-subprocess/blob/873dfed165173e52907beb87118b2c0c05d8b8a1/src/popen.rs#L1117 @@ -179,10 +180,16 @@ impl Command { let mut pi: PROCESS_INFORMATION = unsafe { mem::zeroed() }; - let mut cmdline = self.cmdline()?; + let (mut exe, mut cmdline) = self.cmdline()?; + let cmd_os = OsString::from_wide(&cmdline); + eprintln!( + "Running: module: {:?} {:?}", + OsString::from_wide(&exe), + cmd_os + ); let res = unsafe { CreateProcessW( - ptr::null(), + exe.as_mut_slice().as_mut_ptr(), cmdline.as_mut_slice().as_mut_ptr(), ptr::null_mut(), ptr::null_mut(), @@ -195,11 +202,8 @@ impl Command { ) }; if res == 0 { - bail!( - "CreateProcessW `{:?}` failed: {}", - OsString::from_wide(&cmdline), - IoError::last_os_error() - ); + let err = IoError::last_os_error(); + bail!("CreateProcessW `{:?}` failed: {}", cmd_os, err); } // Make sure we close out the thread handle so we don't leak it; @@ -354,12 +358,20 @@ struct OwnedHandle { unsafe impl Send for OwnedHandle {} impl Drop for OwnedHandle { fn drop(&mut self) { - unsafe { CloseHandle(self.handle) }; + if self.handle != INVALID_HANDLE_VALUE && !self.handle.is_null() { + unsafe { CloseHandle(self.handle) }; + } } } impl OwnedHandle { fn try_clone(&self) -> Result { + if self.handle == INVALID_HANDLE_VALUE || self.handle.is_null() { + return Ok(OwnedHandle { + handle: self.handle, + }); + } + let proc = unsafe { GetCurrentProcess() }; let mut duped = INVALID_HANDLE_VALUE; let ok = unsafe { @@ -448,13 +460,23 @@ impl MasterPty { } pub fn try_clone(&self) -> Result { + // FIXME: this isn't great. Replace this with a way to + // clone the output handle and read it. + let mut inner = self.inner.lock().unwrap(); Ok(Self { - inner: self.inner.clone(), + inner: Arc::new(Mutex::new(Inner { + con: PsuedoCon { + con: INVALID_HANDLE_VALUE, + }, + readable: inner.readable.try_clone()?, + writable: inner.writable.try_clone()?, + size: inner.size, + })), }) } pub fn clear_nonblocking(&self) -> Result<(), Error> { - unimplemented!(); + Ok(()) } }