diff options
author | Joe Wilm <joe@jwilm.com> | 2016-12-29 20:39:30 -0500 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-12-29 20:53:41 -0500 |
commit | b704dafb2420df6f7fca64980a2f52c1a00bcef5 (patch) | |
tree | f4659fa9ba38a8626d478e23d97b331c6dd5f8dc | |
parent | f1336ee1c74c8e3d324ff7b32b562a64046df5ce (diff) | |
download | alacritty-b704dafb2420df6f7fca64980a2f52c1a00bcef5.tar.gz alacritty-b704dafb2420df6f7fca64980a2f52c1a00bcef5.zip |
Fix some bugs with selections
Moving the window on macOS would cause a panic in certain circumstances.
-rw-r--r-- | src/event.rs | 12 | ||||
-rw-r--r-- | src/input.rs | 31 | ||||
-rw-r--r-- | src/main.rs | 6 | ||||
-rw-r--r-- | src/selection.rs | 16 | ||||
-rw-r--r-- | src/term/mod.rs | 53 | ||||
-rw-r--r-- | src/util.rs | 19 |
6 files changed, 101 insertions, 36 deletions
diff --git a/src/event.rs b/src/event.rs index 47621af3..c516f151 100644 --- a/src/event.rs +++ b/src/event.rs @@ -15,6 +15,7 @@ use input::{self, ActionContext, MouseBinding, KeyBinding}; use selection::Selection; use sync::FairMutex; use term::{Term, SizeInfo}; +use util::limit; use window::Window; /// Byte sequences are sent to a `Notify` in response to some events @@ -148,12 +149,13 @@ impl<N: Notify> Processor<N> { *wakeup_request = true; }, glutin::Event::MouseMoved(x, y) => { - if x > 0 && y > 0 { - processor.mouse_moved(x as u32, y as u32); + let x = limit(x, 0, processor.ctx.size_info.width as i32); + let y = limit(y, 0, processor.ctx.size_info.height as i32); - if !processor.ctx.selection.is_empty() { - *wakeup_request = true; - } + processor.mouse_moved(x as u32, y as u32); + + if !processor.ctx.selection.is_empty() { + *wakeup_request = true; } }, glutin::Event::Focused(true) => { diff --git a/src/input.rs b/src/input.rs index 001f541c..84ed86ec 100644 --- a/src/input.rs +++ b/src/input.rs @@ -150,11 +150,12 @@ impl Action { Action::Copy => { if let Some(selection) = ctx.selection.span() { let buf = ctx.terminal.string_from_selection(&selection); - - Clipboard::new() - .expect("get clipboard") - .store_primary(buf) - .expect("copy into clipboard"); + if !buf.is_empty() { + Clipboard::new() + .expect("get clipboard") + .store_primary(buf) + .expect("copy into clipboard"); + } } }, Action::Paste | @@ -193,9 +194,9 @@ impl<'a, N: Notify + 'a> Processor<'a, N> { self.ctx.mouse.x = x; self.ctx.mouse.y = y; - if let Some((line, column)) = self.ctx.size_info.pixels_to_coords(x as usize, y as usize) { - self.ctx.mouse.line = line; - self.ctx.mouse.column = column; + if let Some(point) = self.ctx.size_info.pixels_to_coords(x as usize, y as usize) { + self.ctx.mouse.line = point.line; + self.ctx.mouse.column = point.col; let cell_x = x as usize % self.ctx.size_info.cell_width as usize; let half_cell_width = (self.ctx.size_info.cell_width / 2.0) as usize; @@ -210,8 +211,8 @@ impl<'a, N: Notify + 'a> Processor<'a, N> { !self.ctx.terminal.mode().contains(mode::MOUSE_REPORT_CLICK) { self.ctx.selection.update(Point { - line: line, - col: column + line: point.line, + col: point.col }, self.ctx.mouse.cell_side); } } @@ -248,6 +249,16 @@ impl<'a, N: Notify + 'a> Processor<'a, N> { self.mouse_report(3); return; } + + if let Some(selection) = self.ctx.selection.span() { + let buf = self.ctx.terminal.string_from_selection(&selection); + if !buf.is_empty() { + Clipboard::new() + .expect("get clipboard") + .store_selection(buf) + .expect("copy into clipboard"); + } + } } pub fn on_mouse_wheel(&mut self, delta: MouseScrollDelta, phase: TouchPhase) { diff --git a/src/main.rs b/src/main.rs index aa2da104..0f89aa06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,6 +68,12 @@ fn run(mut config: Config, options: cli::Options) -> Result<(), Box<Error>> { // The display manages a window and can draw the terminal let mut display = Display::new(&config, &options)?; + println!( + "PTY Dimensions: {:?} x {:?}", + display.size().lines(), + display.size().cols() + ); + // Create the terminal // // This object contains all of the state about what's being displayed. It's diff --git a/src/selection.rs b/src/selection.rs index a3ab0ac5..ebc84bee 100644 --- a/src/selection.rs +++ b/src/selection.rs @@ -106,12 +106,16 @@ impl Selection { debug_assert!(!(tail < front)); // Single-cell selections are a special case - if start == end && start_side != end_side { - return Some(Span { - ty: SpanType::Inclusive, - front: *front, - tail: *tail - }); + if start == end { + if start_side != end_side { + return Some(Span { + ty: SpanType::Inclusive, + front: *front, + tail: *tail + }); + } else { + return None; + } } // The other special case is two adjacent cells with no diff --git a/src/term/mod.rs b/src/term/mod.rs index a166b23f..29bf6b83 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -260,7 +260,7 @@ impl SizeInfo { Column((self.width / self.cell_width) as usize) } - pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option<(Line, Column)> { + pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option<Point> { if x > self.width as usize || y > self.height as usize { return None; } @@ -268,7 +268,10 @@ impl SizeInfo { let col = Column(x / (self.cell_width as usize)); let line = Line(y / (self.cell_height as usize)); - Some((line, col)) + Some(Point { + line: cmp::min(line, self.lines() - 1), + col: cmp::min(col, self.cols() - 1) + }) } } @@ -328,45 +331,67 @@ impl Term { } } trait Append<T> : PushChar { - fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: T) -> Range<Column> ; + fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: T) -> Option<Range<Column>>; } use std::ops::{Range, RangeTo, RangeFrom, RangeFull}; impl Append<Range<Column>> for String { - fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: Range<Column>) -> Range<Column> { + fn append( + &mut self, + grid: &Grid<Cell>, + line: Line, + cols: Range<Column> + ) -> Option<Range<Column>> { let line = &grid[line]; let line_length = line.line_length(); let line_end = cmp::min(line_length, cols.end + 1); - for cell in &line[cols.start..line_end] { - self.push(cell.c); - } - cols.start..line_end + if cols.start >= line_end { + None + } else { + for cell in &line[cols.start..line_end] { + self.push(cell.c); + } + + Some(cols.start..line_end) + } } } impl Append<RangeTo<Column>> for String { #[inline] - fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: RangeTo<Column>) -> Range<Column> { + fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: RangeTo<Column>) -> Option<Range<Column>> { self.append(grid, line, Column(0)..cols.end) } } impl Append<RangeFrom<Column>> for String { #[inline] - fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: RangeFrom<Column>) -> Range<Column> { + fn append( + &mut self, + grid: &Grid<Cell>, + line: Line, + cols: RangeFrom<Column> + ) -> Option<Range<Column>> { let range = self.append(grid, line, cols.start..Column(usize::max_value() - 1)); - self.maybe_newline(grid, line, range.end); + range.as_ref() + .map(|range| self.maybe_newline(grid, line, range.end)); range } } impl Append<RangeFull> for String { #[inline] - fn append(&mut self, grid: &Grid<Cell>, line: Line, _: RangeFull) -> Range<Column> { + fn append( + &mut self, + grid: &Grid<Cell>, + line: Line, + _: RangeFull + ) -> Option<Range<Column>> { let range = self.append(grid, line, Column(0)..Column(usize::max_value() - 1)); - self.maybe_newline(grid, line, range.end); + range.as_ref() + .map(|range| self.maybe_newline(grid, line, range.end)); range } } @@ -415,7 +440,7 @@ impl Term { /// line and column returned are also relative to the top left. /// /// Returns None if the coordinates are outside the screen - pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option<(Line, Column)> { + pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option<Point> { self.size_info().pixels_to_coords(x, y) } diff --git a/src/util.rs b/src/util.rs index a5a4807e..cd8bc9a1 100644 --- a/src/util.rs +++ b/src/util.rs @@ -11,7 +11,8 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +use std::cmp; + /// Threading utilities pub mod thread { /// Like `thread::spawn`, but with a `name` argument @@ -29,3 +30,19 @@ pub mod thread { pub use ::std::thread::*; } + +pub fn limit<T: Ord>(value: T, min: T, max: T) -> T { + cmp::min(cmp::max(value, min), max) +} + +#[cfg(test)] +mod tests { + use super::limit; + + #[test] + fn limit_works() { + assert_eq!(10, limit(10, 0, 100)); + assert_eq!(10, limit(5, 10, 100)); + assert_eq!(100, limit(1000, 10, 100)); + } +} |