diff --git a/Cargo.toml b/Cargo.toml index df237669..f173f126 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ clap = "2" fnv = "1" unicode-width = "0.1" arraydeque = "0.4" -glutin = "0.16" +glutin = "0.17" env_logger = "0.5" base64 = "0.9.0" static_assertions = "0.2.5" diff --git a/src/config.rs b/src/config.rs index b50e3243..6b2e27ed 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1903,7 +1903,6 @@ enum Key { LAlt, LBracket, LControl, - LMenu, LShift, LWin, Mail, @@ -1928,7 +1927,6 @@ enum Key { RAlt, RBracket, RControl, - RMenu, RShift, RWin, Semicolon, @@ -2064,7 +2062,6 @@ impl Key { Key::LAlt => LAlt, Key::LBracket => LBracket, Key::LControl => LControl, - Key::LMenu => LMenu, Key::LShift => LShift, Key::LWin => LWin, Key::Mail => Mail, @@ -2089,7 +2086,6 @@ impl Key { Key::RAlt => RAlt, Key::RBracket => RBracket, Key::RControl => RControl, - Key::RMenu => RMenu, Key::RShift => RShift, Key::RWin => RWin, Key::Semicolon => Semicolon, diff --git a/src/display.rs b/src/display.rs index e0453f72..fcf9c2a5 100644 --- a/src/display.rs +++ b/src/display.rs @@ -18,7 +18,7 @@ use std::sync::mpsc; use parking_lot::{MutexGuard}; -use Rgb; +use {LogicalPosition, LogicalSize, PhysicalSize, Rgb}; use cli; use config::Config; use font::{self, Rasterize}; @@ -27,7 +27,8 @@ use renderer::{self, GlyphCache, QuadRenderer}; use selection::Selection; use term::{Term, SizeInfo}; -use window::{self, Size, Pixels, Window, SetInnerSize}; +use window::{self, Window}; + #[derive(Debug)] pub enum Error { @@ -93,8 +94,8 @@ pub struct Display { renderer: QuadRenderer, glyph_cache: GlyphCache, render_timer: bool, - rx: mpsc::Receiver<(u32, u32)>, - tx: mpsc::Sender<(u32, u32)>, + rx: mpsc::Receiver, + tx: mpsc::Sender, meter: Meter, font_size: font::Size, size_info: SizeInfo, @@ -151,10 +152,10 @@ impl Display { info!("device_pixel_ratio: {}", dpr); // Create renderer - let mut renderer = QuadRenderer::new(config, viewport_size)?; + let mut renderer = QuadRenderer::new(config, viewport_size.to_physical(window.hidpi_factor()))?; let (glyph_cache, cell_width, cell_height) = - Self::new_glyph_cache(dpr, &mut renderer, config)?; + Self::new_glyph_cache(dpr as f32, &mut renderer, config)?; let dimensions = options.dimensions() @@ -165,21 +166,21 @@ impl Display { let width = cell_width as u32 * dimensions.columns_u32(); let height = cell_height as u32 * dimensions.lines_u32(); - let new_viewport_size = Size { - width: Pixels(width + 2 * u32::from(config.padding().x)), - height: Pixels(height + 2 * u32::from(config.padding().y)), - }; + let new_viewport_size = LogicalSize::new( + (width + 2 * u32::from(config.padding().x)) as f64, + (height + 2 * u32::from(config.padding().y)) as f64); - window.set_inner_size(&new_viewport_size); - renderer.resize(new_viewport_size.width.0 as _, new_viewport_size.height.0 as _); - viewport_size = new_viewport_size + window.set_inner_size(new_viewport_size); + renderer.resize(new_viewport_size.to_physical(dpr)); + viewport_size = new_viewport_size; } info!("Cell Size: ({} x {})", cell_width, cell_height); + let psize = viewport_size.to_physical(window.hidpi_factor()); let size_info = SizeInfo { - width: viewport_size.width.0 as f32, - height: viewport_size.height.0 as f32, + width: psize.width as f32, + height: psize.height as f32, cell_width: cell_width as f32, cell_height: cell_height as f32, padding_x: f32::from(config.padding().x), @@ -265,7 +266,7 @@ impl Display { } #[inline] - pub fn resize_channel(&self) -> mpsc::Sender<(u32, u32)> { + pub fn resize_channel(&self) -> mpsc::Sender { self.tx.clone() } @@ -287,7 +288,10 @@ impl Display { // Take most recent resize event, if any while let Ok(sz) = self.rx.try_recv() { - new_size = Some(sz); + // Resize events are emitted via glutin/winit with logical sizes + // However the terminal, window and renderer use physical sizes + // so a conversion must be done here + new_size = Some(sz.to_physical(self.window.hidpi_factor())); } // Font size modification detected @@ -297,16 +301,16 @@ impl Display { if new_size == None { // Force a resize to refresh things - new_size = Some((self.size_info.width as u32, - self.size_info.height as u32)); + new_size = Some(PhysicalSize::new(self.size_info.width as f64, + self.size_info.height as f64)); } } // Receive any resize events; only call gl::Viewport on last // available - if let Some((w, h)) = new_size.take() { - self.size_info.width = w as f32; - self.size_info.height = h as f32; + if let Some(psize) = new_size.take() { + self.size_info.width = psize.width as f32; + self.size_info.height = psize.height as f32; let size = &self.size_info; terminal.resize(size); @@ -315,8 +319,8 @@ impl Display { item.on_resize(size) } - self.window.resize(w, h); - self.renderer.resize(w as i32, h as i32); + self.window.resize(psize); + self.renderer.resize(psize); } } @@ -425,6 +429,6 @@ impl Display { padding_y: py, ..} = *terminal.size_info(); let nspot_y = (py + (row + 1) as f32 * ch) as i32; let nspot_x = (px + col as f32 * cw) as i32; - self.window().set_ime_spot(nspot_x, nspot_y); + self.window().set_ime_spot(LogicalPosition::from((nspot_x, nspot_y))); } } diff --git a/src/event.rs b/src/event.rs index 7e8a955c..69a5d0b6 100644 --- a/src/event.rs +++ b/src/event.rs @@ -21,6 +21,7 @@ use term::{Term, SizeInfo, TermMode}; use util::limit; use util::fmt::Red; use window::Window; +use LogicalSize; /// Byte sequences are sent to a `Notify` in response to some events pub trait Notify { @@ -217,7 +218,7 @@ pub struct Processor { wait_for_event: bool, notifier: N, mouse: Mouse, - resize_tx: mpsc::Sender<(u32, u32)>, + resize_tx: mpsc::Sender, ref_test: bool, size_info: SizeInfo, pub selection: Option, @@ -247,7 +248,7 @@ impl Processor { /// pty. pub fn new( notifier: N, - resize_tx: mpsc::Sender<(u32, u32)>, + resize_tx: mpsc::Sender, options: &Options, config: &Config, ref_test: bool, @@ -282,7 +283,7 @@ impl Processor { processor: &mut input::Processor<'a, ActionContext<'a, N>>, event: Event, ref_test: bool, - resize_tx: &mpsc::Sender<(u32, u32)>, + resize_tx: &mpsc::Sender, hide_cursor: &mut bool, window_is_focused: &mut bool, ) { @@ -315,8 +316,8 @@ impl Processor { // FIXME should do a more graceful shutdown ::std::process::exit(0); }, - Resized(w, h) => { - resize_tx.send((w, h)).expect("send new size"); + Resized(lsize) => { + resize_tx.send(lsize).expect("send new size"); processor.ctx.terminal.dirty = true; }, KeyboardInput { input, .. } => { @@ -337,11 +338,10 @@ impl Processor { processor.ctx.terminal.dirty = true; } }, - CursorMoved { position: (x, y), modifiers, .. } => { - let x = x as i32; - let y = y as i32; - let x = limit(x, 0, processor.ctx.size_info.width as i32); - let y = limit(y, 0, processor.ctx.size_info.height as i32); + CursorMoved { position: lpos, modifiers, .. } => { + let (x, y) = lpos.into(); + let x: i32 = limit(x, 0, processor.ctx.size_info.width as i32); + let y: i32 = limit(y, 0, processor.ctx.size_info.height as i32); *hide_cursor = false; processor.mouse_moved(x as u32, y as u32, modifiers); diff --git a/src/input.rs b/src/input.rs index 52775678..6a0881bb 100644 --- a/src/input.rs +++ b/src/input.rs @@ -456,14 +456,15 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { self.ctx.mouse_mut().lines_scrolled = to_scroll % 1.0; }, - MouseScrollDelta::PixelDelta(_x, y) => { + MouseScrollDelta::PixelDelta(lpos) => { match phase { TouchPhase::Started => { // Reset offset to zero self.ctx.mouse_mut().scroll_px = 0; }, TouchPhase::Moved => { - self.ctx.mouse_mut().scroll_px += y as i32; + let (_x, y): (i32, i32) = lpos.into(); + self.ctx.mouse_mut().scroll_px += y; let height = self.ctx.size_info().cell_height as i32; while self.ctx.mouse_mut().scroll_px.abs() >= height { diff --git a/src/lib.rs b/src/lib.rs index d9006fe0..604ae662 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,9 @@ use std::ops::Mul; pub use grid::Grid; pub use term::Term; +/// Re-export size and position types from glutin/winit +pub use glutin::dpi::{PhysicalSize,LogicalSize,LogicalPosition,PhysicalPosition}; + /// Facade around [winit's `MouseCursor`](glutin::MouseCursor) #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum MouseCursor { diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index b006f566..3b870030 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -31,9 +31,7 @@ use notify::{Watcher, watcher, RecursiveMode, DebouncedEvent}; use config::{self, Config, Delta}; use term::{self, cell, RenderableCell}; -use window::{Size, Pixels}; - -use Rgb; +use {PhysicalSize, Rgb}; // Shader paths for live reload static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl"); @@ -476,7 +474,7 @@ const ATLAS_SIZE: i32 = 1024; impl QuadRenderer { // TODO should probably hand this a transform instead of width/height - pub fn new(config: &Config, size: Size>) -> Result { + pub fn new(config: &Config, size: PhysicalSize) -> Result { let program = ShaderProgram::new(config, size)?; let mut vao: GLuint = 0; @@ -636,10 +634,7 @@ impl QuadRenderer { while let Ok(msg) = self.rx.try_recv() { match msg { Msg::ShaderReload => { - self.reload_shaders(config, Size { - width: Pixels(props.width as u32), - height: Pixels(props.height as u32) - }); + self.reload_shaders(config, PhysicalSize::new(props.width as f64, props.height as f64)); } } } @@ -690,7 +685,7 @@ impl QuadRenderer { }) } - pub fn reload_shaders(&mut self, config: &Config, size: Size>) { + pub fn reload_shaders(&mut self, config: &Config, size: PhysicalSize) { warn!("Reloading shaders ..."); let program = match ShaderProgram::new(config, size) { Ok(program) => { @@ -718,13 +713,15 @@ impl QuadRenderer { self.program = program; } - pub fn resize(&mut self, width: i32, height: i32) { + pub fn resize(&mut self, size: PhysicalSize) { + let (width, height) : (u32, u32) = size.into(); + let padding_x = i32::from(self.program.padding_x); let padding_y = i32::from(self.program.padding_y); // viewport unsafe { - gl::Viewport(padding_x, padding_y, width - 2 * padding_x, height - 2 * padding_y); + gl::Viewport(padding_x, padding_y, (width as i32) - 2 * padding_x, (height as i32) - 2 * padding_y); } // update projection @@ -953,7 +950,7 @@ impl ShaderProgram { pub fn new( config: &Config, - size: Size> + size: PhysicalSize ) -> Result { let vertex_source = if cfg!(feature = "live-shader-reload") { None @@ -1021,8 +1018,8 @@ impl ShaderProgram { padding_y: config.padding().y, }; - shader.update_projection(*size.width as f32, *size.height as f32); - + shader.update_projection(size.width as f32, size.height as f32); + shader.deactivate(); Ok(shader) diff --git a/src/window.rs b/src/window.rs index 51a42232..38fdef49 100644 --- a/src/window.rs +++ b/src/window.rs @@ -12,15 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. use std::convert::From; -use std::fmt::{self, Display}; -use std::ops::Deref; +use std::fmt::Display; use gl; -use glutin::{self, ContextBuilder, ControlFlow, CursorState, Event, EventsLoop, +use glutin::{self, ContextBuilder, ControlFlow, Event, EventsLoop, MouseCursor as GlutinMouseCursor, WindowBuilder}; use glutin::GlContext; -use MouseCursor; + +use {LogicalPosition, LogicalSize, MouseCursor, PhysicalSize}; + use cli::Options; use config::WindowConfig; @@ -81,83 +82,7 @@ pub struct DeviceProperties { /// /// This will be 1. on standard displays and may have a different value on /// hidpi displays. - pub scale_factor: f32, -} - -/// Size of the window -#[derive(Debug, Copy, Clone)] -pub struct Size { - pub width: T, - pub height: T, -} - -/// Strongly typed Pixels unit -#[derive(Debug, Copy, Clone)] -pub struct Pixels(pub T); - -/// Strongly typed Points unit -/// -/// Points are like pixels but adjusted for DPI. -#[derive(Debug, Copy, Clone)] -pub struct Points(pub T); - -pub trait ToPoints { - fn to_points(&self, scale: f32) -> Size>; -} - -impl ToPoints for Size> { - #[inline] - fn to_points(&self, _scale: f32) -> Size> { - *self - } -} - -impl ToPoints for Size> { - fn to_points(&self, scale: f32) -> Size> { - let width_pts = (*self.width as f32 / scale) as u32; - let height_pts = (*self.height as f32 / scale) as u32; - - Size { - width: Points(width_pts), - height: Points(height_pts) - } - } -} - -impl Display for Size { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} × {}", self.width, self.height) - } -} - -macro_rules! deref_newtype { - ($($src:ty),+) => { - $( - impl Deref for $src { - type Target = T; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.0 - } - } - )+ - } -} - -deref_newtype! { Points, Pixels } - - -impl Display for Pixels { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}px", self.0) - } -} - -impl Display for Points { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}pts", self.0) - } + pub scale_factor: f64, } impl ::std::error::Error for Error { @@ -208,7 +133,8 @@ fn create_gl_window( ) -> ::std::result::Result { let context = ContextBuilder::new() .with_srgb(srgb) - .with_vsync(true); + .with_vsync(true) + .with_hardware_acceleration(None); ::glutin::GlWindow::new(window, context, event_loop) } @@ -263,19 +189,21 @@ impl Window { /// rasterization depend on DPI and scale factor. pub fn device_properties(&self) -> DeviceProperties { DeviceProperties { - scale_factor: self.window.hidpi_factor(), + scale_factor: self.window.get_hidpi_factor(), } } - pub fn inner_size_pixels(&self) -> Option>> { - self.window - .get_inner_size() - .map(|(w, h)| Size { width: Pixels(w), height: Pixels(h) }) + pub fn inner_size_pixels(&self) -> Option { + self.window.get_inner_size() + } + + pub fn set_inner_size(&mut self, size: LogicalSize) { + self.window.set_inner_size(size); } #[inline] - pub fn hidpi_factor(&self) -> f32 { - self.window.hidpi_factor() + pub fn hidpi_factor(&self) -> f64 { + self.window.get_hidpi_factor() } #[inline] @@ -301,8 +229,8 @@ impl Window { } #[inline] - pub fn resize(&self, width: u32, height: u32) { - self.window.resize(width, height); + pub fn resize(&self, size: PhysicalSize) { + self.window.resize(size); } /// Block waiting for events @@ -331,13 +259,7 @@ impl Window { pub fn set_cursor_visible(&mut self, visible: bool) { if visible != self.cursor_visible { self.cursor_visible = visible; - if let Err(err) = self.window.set_cursor_state(if visible { - CursorState::Normal - } else { - CursorState::Hide - }) { - warn!("Failed to set cursor visibility: {}", err); - } + self.window.hide_cursor(!visible); } } @@ -361,8 +283,8 @@ impl Window { #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))] pub fn set_urgent(&self, _is_urgent: bool) {} - pub fn set_ime_spot(&self, x: i32, y: i32) { - self.window.set_ime_spot(x, y); + pub fn set_ime_spot(&self, pos: LogicalPosition) { + self.window.set_ime_spot(pos); } #[cfg(not(target_os = "macos"))] @@ -439,14 +361,3 @@ impl Proxy { self.inner.wakeup().unwrap(); } } - -pub trait SetInnerSize { - fn set_inner_size(&mut self, size: &S); -} - -impl SetInnerSize> for Window { - fn set_inner_size(&mut self, size: &T) { - let size = size.to_points(self.hidpi_factor()); - self.window.set_inner_size(*size.width as _, *size.height as _); - } -}