diff --git a/src/event.rs b/src/event.rs index 14ec0b0e..b0987d58 100644 --- a/src/event.rs +++ b/src/event.rs @@ -154,8 +154,8 @@ pub enum ClickState { /// State of the mouse pub struct Mouse { - pub x: u32, - pub y: u32, + pub x: usize, + pub y: usize, pub left_button_state: ElementState, pub middle_button_state: ElementState, pub right_button_state: ElementState, @@ -315,13 +315,11 @@ 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); + let x = limit(x as i32, 0, processor.ctx.size_info.width as i32); + let y = limit(y as i32, 0, processor.ctx.size_info.height as i32); *hide_cursor = false; - processor.mouse_moved(x as u32, y as u32, modifiers); + processor.mouse_moved(x as usize, y as usize, modifiers); }, MouseWheel { delta, phase, modifiers, .. } => { *hide_cursor = false; diff --git a/src/input.rs b/src/input.rs index 7b9eda56..98e0d241 100644 --- a/src/input.rs +++ b/src/input.rs @@ -266,55 +266,52 @@ impl From<&'static str> for Action { impl<'a, A: ActionContext + 'a> Processor<'a, A> { #[inline] - pub fn mouse_moved(&mut self, x: u32, y: u32, modifiers: ModifiersState) { + pub fn mouse_moved(&mut self, x: usize, y: usize, modifiers: ModifiersState) { self.ctx.mouse_mut().x = x; self.ctx.mouse_mut().y = y; let size_info = self.ctx.size_info(); - if let Some(point) = size_info.pixels_to_coords(x as usize, y as usize) { - let prev_line = mem::replace(&mut self.ctx.mouse_mut().line, point.line); - let prev_col = mem::replace(&mut self.ctx.mouse_mut().column, point.col); + let point = size_info.pixels_to_coords(x, y); - let cell_x = (x as usize - size_info.padding_x as usize) % size_info.cell_width as usize; - let half_cell_width = (size_info.cell_width / 2.0) as usize; + let prev_line = mem::replace(&mut self.ctx.mouse_mut().line, point.line); + let prev_col = mem::replace(&mut self.ctx.mouse_mut().column, point.col); - let cell_side = if cell_x > half_cell_width - // Edge case when mouse leaves the window - || x as f32 >= size_info.width - size_info.padding_x - { - Side::Right - } else { - Side::Left - }; - self.ctx.mouse_mut().cell_side = cell_side; + let cell_x = x.saturating_sub(size_info.padding_x as usize) % size_info.cell_width as usize; + let half_cell_width = (size_info.cell_width / 2.0) as usize; - let motion_mode = TermMode::MOUSE_MOTION | TermMode::MOUSE_DRAG; - if self.ctx.mouse_mut().left_button_state == ElementState::Pressed - && ( - modifiers.shift - || !self.ctx.terminal_mode().intersects(TermMode::MOUSE_REPORT_CLICK | motion_mode) - ) - { - self.ctx.update_selection(Point { - line: point.line, - col: point.col - }, cell_side); - } else if self.ctx.terminal_mode().intersects(motion_mode) - // Only report motion when changing cells - && ( - prev_line != self.ctx.mouse_mut().line - || prev_col != self.ctx.mouse_mut().column - ) - { - if self.ctx.mouse_mut().left_button_state == ElementState::Pressed { - self.mouse_report(32, ElementState::Pressed, modifiers); - } else if self.ctx.mouse_mut().middle_button_state == ElementState::Pressed { - self.mouse_report(33, ElementState::Pressed, modifiers); - } else if self.ctx.mouse_mut().right_button_state == ElementState::Pressed { - self.mouse_report(34, ElementState::Pressed, modifiers); - } else if self.ctx.terminal_mode().contains(TermMode::MOUSE_MOTION) { - self.mouse_report(35, ElementState::Pressed, modifiers); - } + let cell_side = if cell_x > half_cell_width + // Edge case when mouse leaves the window + || x as f32 >= size_info.width - size_info.padding_x + { + Side::Right + } else { + Side::Left + }; + self.ctx.mouse_mut().cell_side = cell_side; + + let motion_mode = TermMode::MOUSE_MOTION | TermMode::MOUSE_DRAG; + let report_mode = TermMode::MOUSE_REPORT_CLICK | motion_mode; + + if self.ctx.mouse_mut().left_button_state == ElementState::Pressed && + ( modifiers.shift || !self.ctx.terminal_mode().intersects(report_mode)) + { + self.ctx.update_selection(Point { + line: point.line, + col: point.col + }, cell_side); + } else if self.ctx.terminal_mode().intersects(motion_mode) + // Only report motion when changing cells + && (prev_line != self.ctx.mouse_mut().line || prev_col != self.ctx.mouse_mut().column) + && size_info.contains_point(x, y) + { + if self.ctx.mouse_mut().left_button_state == ElementState::Pressed { + self.mouse_report(32, ElementState::Pressed, modifiers); + } else if self.ctx.mouse_mut().middle_button_state == ElementState::Pressed { + self.mouse_report(33, ElementState::Pressed, modifiers); + } else if self.ctx.mouse_mut().right_button_state == ElementState::Pressed { + self.mouse_report(34, ElementState::Pressed, modifiers); + } else if self.ctx.terminal_mode().contains(TermMode::MOUSE_MOTION) { + self.mouse_report(35, ElementState::Pressed, modifiers); } } } diff --git a/src/selection.rs b/src/selection.rs index 8e7fa29b..d49236a4 100644 --- a/src/selection.rs +++ b/src/selection.rs @@ -253,8 +253,31 @@ impl Selection { // Handle some edge cases if start.line > end.line { - start.col += 1; - end.col -= 1; + if end.col > Column(0) { + start.col += 1; + end.col -= 1; + } + // Special case for when a multi-line selection to the + // bottom ends on a new line with just one cell selected + // and the first cell should not be selected + else { + if start_side == Side::Right { + start.col += 1; + } + + // Remove the single selected cell if mouse left window + if end_side == Side::Left { + end.line += 1; + end.col = cols - 1; + } + + return Some(Span { + cols, + front: end, + tail: start, + ty: SpanType::Inclusive, + }); + } } else if start.line < end.line { start.col -= 1; end.col += 1; diff --git a/src/term/mod.rs b/src/term/mod.rs index 6318c680..8db21402 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -791,25 +791,21 @@ impl SizeInfo { Column(((self.width - 2. * self.padding_x) / self.cell_width) as usize) } - fn contains_point(&self, x: usize, y:usize) -> bool { + pub fn contains_point(&self, x: usize, y:usize) -> bool { x <= (self.width - self.padding_x) as usize && x >= self.padding_x as usize && y <= (self.height - self.padding_y) as usize && y >= self.padding_y as usize } - pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option { - if !self.contains_point(x, y) { - return None; - } + pub fn pixels_to_coords(&self, x: usize, y: usize) -> Point { + let col = Column(x.saturating_sub(self.padding_x as usize) / (self.cell_width as usize)); + let line = Line(y.saturating_sub(self.padding_y as usize) / (self.cell_height as usize)); - let col = Column((x - self.padding_x as usize) / (self.cell_width as usize)); - let line = Line((y - self.padding_y as usize) / (self.cell_height as usize)); - - Some(Point { + Point { line: min(line, self.lines() - 1), col: min(col, self.cols() - 1) - }) + } } } @@ -1036,7 +1032,11 @@ impl Term { /// /// Returns None if the coordinates are outside the screen pub fn pixels_to_coords(&self, x: usize, y: usize) -> Option { - self.size_info().pixels_to_coords(x, y) + if self.size_info.contains_point(x, y) { + Some(self.size_info.pixels_to_coords(x, y)) + } else { + None + } } /// Access to the raw grid data structure