aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/event.rs12
-rw-r--r--src/input.rs31
-rw-r--r--src/main.rs6
-rw-r--r--src/selection.rs16
-rw-r--r--src/term/mod.rs53
-rw-r--r--src/util.rs19
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));
+ }
+}