@@ -1,26 +1,22 @@
use alacritty_terminal::{
ansi::{Color as AnsiColor, Color::Named, CursorShape as AlacCursorShape, NamedColor},
- grid::{Dimensions, Scroll},
- index::{Column as GridCol, Direction, Line as GridLine, Point, Side},
+ grid::Dimensions,
+ index::Point,
selection::SelectionRange,
- term::{
- cell::{Cell, Flags},
- TermMode,
- },
+ term::cell::{Cell, Flags},
};
use editor::{Cursor, CursorShape, HighlightedRange, HighlightedRangeLine};
use gpui::{
color::Color,
- elements::*,
fonts::{Properties, Style::Italic, TextStyle, Underline, Weight},
geometry::{
rect::RectF,
vector::{vec2f, Vector2F},
},
- json::json,
+ serde_json::json,
text_layout::{Line, RunStyle},
- Event, EventContext, FontCache, KeyDownEvent, ModelContext, MouseButton, MouseButtonEvent,
- MouseRegion, PaintContext, Quad, ScrollWheelEvent, TextLayoutCache, WeakModelHandle,
+ Element, Event, EventContext, FontCache, KeyDownEvent, ModelContext, MouseButton,
+ MouseButtonEvent, MouseRegion, PaintContext, Quad, TextLayoutCache, WeakModelHandle,
WeakViewHandle,
};
use itertools::Itertools;
@@ -29,12 +25,11 @@ use settings::Settings;
use theme::TerminalStyle;
use util::ResultExt;
+use std::fmt::Debug;
use std::{
- cmp::min,
mem,
ops::{Deref, Range},
};
-use std::{fmt::Debug, ops::Sub};
use crate::{
connected_view::{ConnectedView, DeployContextMenu},
@@ -42,11 +37,6 @@ use crate::{
Terminal, TerminalSize,
};
-///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
-///Scroll multiplier that is set to 3 by default. This will be removed when I
-///Implement scroll bars.
-pub const ALACRITTY_SCROLL_MULTIPLIER: f32 = 3.;
-
///The information generated during layout that is nescessary for painting
pub struct LayoutState {
cells: Vec<LayoutCell>,
@@ -56,7 +46,6 @@ pub struct LayoutState {
background_color: Color,
selection_color: Color,
size: TerminalSize,
- display_offset: usize,
}
#[derive(Debug)]
@@ -420,22 +409,13 @@ impl TerminalEl {
fn generic_button_handler(
connection: WeakModelHandle<Terminal>,
origin: Vector2F,
- cur_size: TerminalSize,
- display_offset: usize,
- f: impl Fn(&mut Terminal, Point, Direction, MouseButtonEvent, &mut ModelContext<Terminal>),
+ f: impl Fn(&mut Terminal, Vector2F, MouseButtonEvent, &mut ModelContext<Terminal>),
) -> impl Fn(MouseButtonEvent, &mut EventContext) {
move |event, cx| {
cx.focus_parent_view();
if let Some(conn_handle) = connection.upgrade(cx.app) {
conn_handle.update(cx.app, |terminal, cx| {
- let (point, side) = TerminalEl::mouse_to_cell_data(
- event.position,
- origin,
- cur_size,
- display_offset,
- );
-
- f(terminal, point, side, event, cx);
+ f(terminal, origin, event, cx);
cx.notify();
})
@@ -448,8 +428,6 @@ impl TerminalEl {
origin: Vector2F,
view_id: usize,
visible_bounds: RectF,
- cur_size: TerminalSize,
- display_offset: usize,
cx: &mut PaintContext,
) {
let connection = self.terminal;
@@ -459,34 +437,20 @@ impl TerminalEl {
if cx.is_parent_view_focused() {
if let Some(conn_handle) = connection.upgrade(cx.app) {
conn_handle.update(cx.app, |terminal, cx| {
- let (point, side) = TerminalEl::mouse_to_cell_data(
- event.position,
- origin,
- cur_size,
- display_offset,
- );
-
- terminal.mouse_move(point, side, &event);
-
+ terminal.mouse_move(&event, origin);
cx.notify();
})
}
}
})
.on_drag(MouseButton::Left, move |_prev, event, cx| {
- if let Some(conn_handle) = connection.upgrade(cx.app) {
- conn_handle.update(cx.app, |terminal, cx| {
- let (point, side) = TerminalEl::mouse_to_cell_data(
- event.position,
- origin,
- cur_size,
- display_offset,
- );
-
- terminal.mouse_drag(point, side);
-
- cx.notify();
- })
+ if cx.is_parent_view_focused() {
+ if let Some(conn_handle) = connection.upgrade(cx.app) {
+ conn_handle.update(cx.app, |terminal, cx| {
+ terminal.mouse_drag(event, origin);
+ cx.notify();
+ })
+ }
}
})
.on_down(
@@ -494,10 +458,8 @@ impl TerminalEl {
TerminalEl::generic_button_handler(
connection,
origin,
- cur_size,
- display_offset,
- move |terminal, point, side, _e, _cx| {
- terminal.mouse_down(point, side);
+ move |terminal, origin, e, _cx| {
+ terminal.mouse_down(&e, origin);
},
),
)
@@ -506,10 +468,8 @@ impl TerminalEl {
TerminalEl::generic_button_handler(
connection,
origin,
- cur_size,
- display_offset,
- move |terminal, point, side, _e, _cx| {
- terminal.mouse_down(point, side);
+ move |terminal, origin, e, _cx| {
+ terminal.mouse_down(&e, origin);
},
),
)
@@ -518,65 +478,61 @@ impl TerminalEl {
TerminalEl::generic_button_handler(
connection,
origin,
- cur_size,
- display_offset,
- move |terminal, point, side, _e, _cx| {
- terminal.mouse_down(point, side);
+ move |terminal, origin, e, _cx| {
+ terminal.mouse_down(&e, origin);
},
),
)
- //TODO
- .on_click(
+ .on_up(
MouseButton::Left,
TerminalEl::generic_button_handler(
connection,
origin,
- cur_size,
- display_offset,
- move |terminal, point, side, e, _cx| {
- terminal.click(point, side, e.click_count);
+ move |terminal, origin, e, _cx| {
+ terminal.mouse_up(&e, origin);
},
),
)
- .on_click(
+ .on_up(
+ MouseButton::Right,
+ TerminalEl::generic_button_handler(
+ connection,
+ origin,
+ move |terminal, origin, e, _cx| {
+ terminal.mouse_up(&e, origin);
+ },
+ ),
+ )
+ .on_up(
MouseButton::Middle,
TerminalEl::generic_button_handler(
connection,
origin,
- cur_size,
- display_offset,
- move |terminal, point, side, e, _cx| {
- terminal.click(point, side, e.click_count);
+ move |terminal, origin, e, _cx| {
+ terminal.mouse_up(&e, origin);
+ },
+ ),
+ )
+ .on_click(
+ MouseButton::Left,
+ TerminalEl::generic_button_handler(
+ connection,
+ origin,
+ move |terminal, origin, e, _cx| {
+ terminal.left_click(&e, origin);
},
),
)
.on_click(
MouseButton::Right,
move |e @ MouseButtonEvent { position, .. }, cx| {
- //Attempt to check the mode
- if let Some(conn_handle) = connection.upgrade(cx.app) {
- let handled = conn_handle.update(cx.app, |terminal, _cx| {
- //Finally, we can check the mode!
- if terminal.last_mode.intersects(TermMode::MOUSE_MODE) {
- let (point, side) = TerminalEl::mouse_to_cell_data(
- position,
- origin,
- cur_size,
- display_offset,
- );
-
- terminal.click(point, side, e.click_count);
- true
- } else {
- false
- }
- });
-
- //If I put this up by the true, then we're in the wrong 'cx'
- if !handled {
- cx.dispatch_action(DeployContextMenu { position });
- }
+ let mouse_mode = if let Some(conn_handle) = connection.upgrade(cx.app) {
+ conn_handle.update(cx.app, |terminal, _cx| terminal.mouse_mode(e.shift))
} else {
+ //If we can't get the model handle, probably can't deploy the context menu
+ true
+ };
+ if !mouse_mode {
cx.dispatch_action(DeployContextMenu { position });
}
},
@@ -615,47 +571,6 @@ impl TerminalEl {
underline: Default::default(),
}
}
-
- pub fn mouse_to_cell_data(
- pos: Vector2F,
- origin: Vector2F,
- cur_size: TerminalSize,
- display_offset: usize,
- ) -> (Point, alacritty_terminal::index::Direction) {
- let pos = pos.sub(origin);
- let point = {
- let col = pos.x() / cur_size.cell_width; //TODO: underflow...
- let col = min(GridCol(col as usize), cur_size.last_column());
-
- let line = pos.y() / cur_size.line_height;
- let line = min(line as i32, cur_size.bottommost_line().0);
-
- Point::new(GridLine(line - display_offset as i32), col)
- };
-
- //Copied (with modifications) from alacritty/src/input.rs > Processor::cell_side()
- let side = {
- let x = pos.0.x() as usize;
- let cell_x =
- x.saturating_sub(cur_size.cell_width as usize) % cur_size.cell_width as usize;
- let half_cell_width = (cur_size.cell_width / 2.0) as usize;
-
- let additional_padding =
- (cur_size.width() - cur_size.cell_width * 2.) % cur_size.cell_width;
- let end_of_grid = cur_size.width() - cur_size.cell_width - additional_padding;
- //Width: Pixels or columns?
- if cell_x > half_cell_width
- // Edge case when mouse leaves the window.
- || x as f32 >= end_of_grid
- {
- Side::Right
- } else {
- Side::Left
- }
- };
-
- (point, side)
- }
}
impl Element for TerminalEl {
@@ -712,7 +627,7 @@ impl Element for TerminalEl {
(
cells,
- dbg!(content.selection),
+ content.selection,
content.cursor,
content.display_offset,
cursor_text,
@@ -794,7 +709,6 @@ impl Element for TerminalEl {
size: dimensions,
rects,
highlights,
- display_offset,
},
)
}
@@ -813,14 +727,7 @@ impl Element for TerminalEl {
let origin = bounds.origin() + vec2f(layout.size.cell_width, 0.);
//Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
- self.attach_mouse_handlers(
- origin,
- self.view.id(),
- visible_bounds,
- layout.size,
- layout.display_offset,
- cx,
- );
+ self.attach_mouse_handlers(origin, self.view.id(), visible_bounds, cx);
cx.paint_layer(clip_bounds, |cx| {
//Start with a background color
@@ -884,28 +791,22 @@ impl Element for TerminalEl {
fn dispatch_event(
&mut self,
event: &gpui::Event,
- _bounds: gpui::geometry::rect::RectF,
+ bounds: gpui::geometry::rect::RectF,
visible_bounds: gpui::geometry::rect::RectF,
layout: &mut Self::LayoutState,
_paint: &mut Self::PaintState,
cx: &mut gpui::EventContext,
) -> bool {
match event {
- Event::ScrollWheel(ScrollWheelEvent {
- delta, position, ..
- }) => visible_bounds
- .contains_point(*position)
+ Event::ScrollWheel(e) => visible_bounds
+ .contains_point(e.position)
.then(|| {
- let scroll_lines =
- (delta.y() / layout.size.line_height) * ALACRITTY_SCROLL_MULTIPLIER;
+ let origin = bounds.origin() + vec2f(layout.size.cell_width, 0.);
if let Some(terminal) = self.terminal.upgrade(cx.app) {
- terminal.update(cx.app, |term, _| {
- term.scroll(Scroll::Delta(scroll_lines.round() as i32))
- });
+ terminal.update(cx.app, |term, _| term.scroll(e, origin));
+ cx.notify();
}
-
- cx.notify();
})
.is_some(),
Event::KeyDown(KeyDownEvent { keystroke, .. }) => {
@@ -913,7 +814,6 @@ impl Element for TerminalEl {
return false;
}
- //TODO Talk to keith about how to catch events emitted from an element.
if let Some(view) = self.view.upgrade(cx.app) {
view.update(cx.app, |view, cx| {
view.clear_bel(cx);
@@ -969,36 +869,3 @@ impl Element for TerminalEl {
Some(layout.cursor.as_ref()?.bounding_rect(origin))
}
}
-
-mod test {
-
- #[test]
- fn test_mouse_to_selection() {
- let term_width = 100.;
- let term_height = 200.;
- let cell_width = 10.;
- let line_height = 20.;
- let mouse_pos_x = 100.; //Window relative
- let mouse_pos_y = 100.; //Window relative
- let origin_x = 10.;
- let origin_y = 20.;
-
- let cur_size = crate::connected_el::TerminalSize::new(
- line_height,
- cell_width,
- gpui::geometry::vector::vec2f(term_width, term_height),
- );
-
- let mouse_pos = gpui::geometry::vector::vec2f(mouse_pos_x, mouse_pos_y);
- let origin = gpui::geometry::vector::vec2f(origin_x, origin_y); //Position of terminal window, 1 'cell' in
- let (point, _) =
- crate::connected_el::TerminalEl::mouse_to_cell_data(mouse_pos, origin, cur_size, 0);
- assert_eq!(
- point,
- alacritty_terminal::index::Point::new(
- alacritty_terminal::index::Line(((mouse_pos_y - origin_y) / line_height) as i32),
- alacritty_terminal::index::Column(((mouse_pos_x - origin_x) / cell_width) as usize),
- )
- );
- }
-}
@@ -1,16 +1,23 @@
+use std::cmp::min;
+use std::iter::repeat;
+
+use alacritty_terminal::grid::Dimensions;
/// Most of the code, and specifically the constants, in this are copied from Alacritty,
/// with modifications for our circumstances
-use alacritty_terminal::{index::Point, term::TermMode};
-use gpui::{MouseButtonEvent, MouseMovedEvent, ScrollWheelEvent};
+use alacritty_terminal::index::{Column as GridCol, Line as GridLine, Point, Side};
+use alacritty_terminal::term::TermMode;
+use gpui::{geometry::vector::Vector2F, MouseButtonEvent, MouseMovedEvent, ScrollWheelEvent};
+
+use crate::TerminalSize;
-pub struct Modifiers {
+struct Modifiers {
ctrl: bool,
shift: bool,
alt: bool,
}
impl Modifiers {
- pub fn from_moved(e: &MouseMovedEvent) -> Self {
+ fn from_moved(e: &MouseMovedEvent) -> Self {
Modifiers {
ctrl: e.ctrl,
shift: e.shift,
@@ -18,7 +25,7 @@ impl Modifiers {
}
}
- pub fn from_button(e: &MouseButtonEvent) -> Self {
+ fn from_button(e: &MouseButtonEvent) -> Self {
Modifiers {
ctrl: e.ctrl,
shift: e.shift,
@@ -27,7 +34,7 @@ impl Modifiers {
}
//TODO: Determine if I should add modifiers into the ScrollWheelEvent type
- pub fn from_scroll() -> Self {
+ fn from_scroll() -> Self {
Modifiers {
ctrl: false,
shift: false,
@@ -36,13 +43,13 @@ impl Modifiers {
}
}
-pub enum MouseFormat {
+enum MouseFormat {
SGR,
Normal(bool),
}
impl MouseFormat {
- pub fn from_mode(mode: TermMode) -> Self {
+ fn from_mode(mode: TermMode) -> Self {
if mode.contains(TermMode::SGR_MOUSE) {
MouseFormat::SGR
} else if mode.contains(TermMode::UTF8_MOUSE) {
@@ -53,7 +60,7 @@ impl MouseFormat {
}
}
-pub enum MouseButton {
+enum MouseButton {
LeftButton = 0,
MiddleButton = 1,
RightButton = 2,
@@ -67,7 +74,7 @@ pub enum MouseButton {
}
impl MouseButton {
- pub fn from_move(e: &MouseMovedEvent) -> Self {
+ fn from_move(e: &MouseMovedEvent) -> Self {
match e.pressed_button {
Some(b) => match b {
gpui::MouseButton::Left => MouseButton::LeftMove,
@@ -79,7 +86,7 @@ impl MouseButton {
}
}
- pub fn from_button(e: &MouseButtonEvent) -> Self {
+ fn from_button(e: &MouseButtonEvent) -> Self {
match e.button {
gpui::MouseButton::Left => MouseButton::LeftButton,
gpui::MouseButton::Right => MouseButton::MiddleButton,
@@ -88,7 +95,7 @@ impl MouseButton {
}
}
- pub fn from_scroll(e: &ScrollWheelEvent) -> Self {
+ fn from_scroll(e: &ScrollWheelEvent) -> Self {
if e.delta.y() > 0. {
MouseButton::ScrollUp
} else {
@@ -96,7 +103,7 @@ impl MouseButton {
}
}
- pub fn is_other(&self) -> bool {
+ fn is_other(&self) -> bool {
match self {
MouseButton::Other => true,
_ => false,
@@ -109,24 +116,31 @@ pub fn scroll_report(
scroll_lines: i32,
e: &ScrollWheelEvent,
mode: TermMode,
-) -> Option<Vec<Vec<u8>>> {
+) -> Option<impl Iterator<Item = Vec<u8>>> {
if mode.intersects(TermMode::MOUSE_MODE) && scroll_lines >= 1 {
- if let Some(report) = mouse_report(
+ mouse_report(
point,
MouseButton::from_scroll(e),
true,
Modifiers::from_scroll(),
MouseFormat::from_mode(mode),
- ) {
- let mut res = vec![];
- for _ in 0..scroll_lines.abs() {
- res.push(report.clone());
- }
- return Some(res);
- }
+ )
+ .map(|report| repeat(report).take(scroll_lines as usize))
+ } else {
+ None
}
+}
- None
+pub fn alt_scroll(scroll_lines: i32) -> Vec<u8> {
+ let cmd = if scroll_lines > 0 { b'A' } else { b'B' };
+
+ let mut content = Vec::with_capacity(scroll_lines as usize * 3);
+ for _ in 0..scroll_lines {
+ content.push(0x1b);
+ content.push(b'O');
+ content.push(cmd);
+ }
+ content
}
pub fn mouse_button_report(
@@ -164,6 +178,31 @@ pub fn mouse_moved_report(point: Point, e: &MouseMovedEvent, mode: TermMode) ->
}
}
+pub fn mouse_side(pos: Vector2F, cur_size: TerminalSize) -> alacritty_terminal::index::Direction {
+ let x = pos.0.x() as usize;
+ let cell_x = x.saturating_sub(cur_size.cell_width as usize) % cur_size.cell_width as usize;
+ let half_cell_width = (cur_size.cell_width / 2.0) as usize;
+ let additional_padding = (cur_size.width() - cur_size.cell_width * 2.) % cur_size.cell_width;
+ let end_of_grid = cur_size.width() - cur_size.cell_width - additional_padding;
+ //Width: Pixels or columns?
+ if cell_x > half_cell_width
+ // Edge case when mouse leaves the window.
+ || x as f32 >= end_of_grid
+ {
+ Side::Right
+ } else {
+ Side::Left
+ }
+}
+
+pub fn mouse_point(pos: Vector2F, cur_size: TerminalSize, display_offset: usize) -> Point {
+ let col = pos.x() / cur_size.cell_width;
+ let col = min(GridCol(col as usize), cur_size.last_column());
+ let line = pos.y() / cur_size.line_height;
+ let line = min(line as i32, cur_size.bottommost_line().0);
+ Point::new(GridLine(line - display_offset as i32), col)
+}
+
///Generate the bytes to send to the terminal, from the cell location, a mouse event, and the terminal mode
fn mouse_report(
point: Point,
@@ -246,3 +285,38 @@ fn sgr_mouse_report(point: Point, button: u8, pressed: bool) -> String {
msg
}
+
+#[cfg(test)]
+mod test {
+ use crate::mappings::mouse::mouse_point;
+
+ #[test]
+ fn test_mouse_to_selection() {
+ let term_width = 100.;
+ let term_height = 200.;
+ let cell_width = 10.;
+ let line_height = 20.;
+ let mouse_pos_x = 100.; //Window relative
+ let mouse_pos_y = 100.; //Window relative
+ let origin_x = 10.;
+ let origin_y = 20.;
+
+ let cur_size = crate::TerminalSize::new(
+ line_height,
+ cell_width,
+ gpui::geometry::vector::vec2f(term_width, term_height),
+ );
+
+ let mouse_pos = gpui::geometry::vector::vec2f(mouse_pos_x, mouse_pos_y);
+ let origin = gpui::geometry::vector::vec2f(origin_x, origin_y); //Position of terminal window, 1 'cell' in
+ let mouse_pos = mouse_pos - origin;
+ let point = mouse_point(mouse_pos, cur_size, 0);
+ assert_eq!(
+ point,
+ alacritty_terminal::index::Point::new(
+ alacritty_terminal::index::Line(((mouse_pos_y - origin_y) / line_height) as i32),
+ alacritty_terminal::index::Column(((mouse_pos_x - origin_x) / cell_width) as usize),
+ )
+ );
+ }
+}
@@ -24,16 +24,19 @@ use futures::{
FutureExt,
};
-use mappings::mouse::mouse_moved_report;
+use mappings::mouse::{
+ alt_scroll, mouse_button_report, mouse_moved_report, mouse_point, mouse_side, scroll_report,
+};
use modal::deploy_modal;
use settings::{Settings, Shell, TerminalBlink};
-use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc, time::Duration};
+use std::{collections::HashMap, fmt::Display, ops::Sub, path::PathBuf, sync::Arc, time::Duration};
use thiserror::Error;
use gpui::{
geometry::vector::{vec2f, Vector2F},
keymap::Keystroke,
- ClipboardItem, Entity, ModelContext, MouseMovedEvent, MutableAppContext,
+ ClipboardItem, Entity, ModelContext, MouseButtonEvent, MouseMovedEvent, MutableAppContext,
+ ScrollWheelEvent,
};
use crate::mappings::{
@@ -49,6 +52,11 @@ pub fn init(cx: &mut MutableAppContext) {
connected_view::init(cx);
}
+///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
+///Scroll multiplier that is set to 3 by default. This will be removed when I
+///Implement scroll bars.
+pub const ALACRITTY_SCROLL_MULTIPLIER: f32 = 3.;
+
const DEBUG_TERMINAL_WIDTH: f32 = 500.;
const DEBUG_TERMINAL_HEIGHT: f32 = 30.;
const DEBUG_CELL_WIDTH: f32 = 5.;
@@ -348,6 +356,7 @@ impl TerminalBuilder {
last_mode: TermMode::NONE,
cur_size: initial_size,
last_mouse: None,
+ last_offset: 0,
};
Ok(TerminalBuilder {
@@ -417,6 +426,7 @@ pub struct Terminal {
title: String,
cur_size: TerminalSize,
last_mode: TermMode,
+ last_offset: usize,
last_mouse: Option<(Point, Direction)>,
}
@@ -509,7 +519,7 @@ impl Terminal {
}
pub fn input(&mut self, input: String) {
- self.scroll(Scroll::Bottom);
+ self.events.push(InternalEvent::Scroll(Scroll::Bottom));
self.events.push(InternalEvent::SetSelection(None));
self.write_to_pty(input);
}
@@ -563,11 +573,12 @@ impl Terminal {
self.process_terminal_event(&e, &mut term, cx)
}
- // self.utilization = Self::estimate_utilization(term.take_last_processed_bytes());
self.last_mode = *term.mode();
let content = term.renderable_content();
+ self.last_offset = content.display_offset;
+
let cursor_text = term.grid()[content.cursor.point].c;
f(content, cursor_text)
@@ -602,23 +613,45 @@ impl Terminal {
}
}
- /// Handle a mouse move
- pub fn mouse_move(&mut self, point: Point, side: Direction, e: &MouseMovedEvent) {
- if self.mouse_changed(point, side) {
+ pub fn mouse_mode(&self, shift: bool) -> bool {
+ self.last_mode.intersects(TermMode::MOUSE_MODE) && !shift
+ }
+
+ pub fn mouse_move(&mut self, e: &MouseMovedEvent, origin: Vector2F) {
+ let position = e.position.sub(origin);
+
+ let point = mouse_point(position, self.cur_size, self.last_offset);
+ let side = mouse_side(position, self.cur_size);
+
+ if self.mouse_changed(point, side) && self.mouse_mode(e.shift) {
if let Some(bytes) = mouse_moved_report(point, e, self.last_mode) {
self.pty_tx.notify(bytes);
}
}
}
- pub fn mouse_drag(&mut self, point: Point, side: Direction) {
- self.events
- .push(InternalEvent::UpdateSelection((point, side)));
+ pub fn mouse_drag(&mut self, e: MouseMovedEvent, origin: Vector2F) {
+ let position = e.position.sub(origin);
+
+ if !self.mouse_mode(e.shift) {
+ let point = mouse_point(position, self.cur_size, self.last_offset);
+ let side = mouse_side(position, self.cur_size);
+
+ self.events
+ .push(InternalEvent::UpdateSelection((point, side)));
+ }
}
- pub fn mouse_down(&mut self, point: Point, side: Direction) {
- if self.last_mode.intersects(TermMode::MOUSE_REPORT_CLICK) {
- //TODE: MOUSE MODE
+ pub fn mouse_down(&mut self, e: &MouseButtonEvent, origin: Vector2F) {
+ let position = e.position.sub(origin);
+
+ let point = mouse_point(position, self.cur_size, self.last_offset);
+ let side = mouse_side(position, self.cur_size);
+
+ if self.mouse_mode(e.shift) {
+ if let Some(bytes) = mouse_button_report(point, e, true, self.last_mode) {
+ self.pty_tx.notify(bytes);
+ }
} else {
self.events
.push(InternalEvent::SetSelection(Some(Selection::new(
@@ -629,11 +662,15 @@ impl Terminal {
}
}
- pub fn click(&mut self, point: Point, side: Direction, clicks: usize) {
- if self.last_mode.intersects(TermMode::MOUSE_MODE) {
- //TODE: MOUSE MODE
- } else {
- let selection_type = match clicks {
+ pub fn left_click(&mut self, e: &MouseButtonEvent, origin: Vector2F) {
+ let position = e.position.sub(origin);
+ //TODO: Alt-click cursor position
+
+ if !self.mouse_mode(e.shift) {
+ let point = mouse_point(position, self.cur_size, self.last_offset);
+ let side = mouse_side(position, self.cur_size);
+
+ let selection_type = match e.click_count {
0 => return, //This is a release
1 => Some(SelectionType::Simple),
2 => Some(SelectionType::Semantic),
@@ -648,13 +685,55 @@ impl Terminal {
}
}
- ///Scroll the terminal
- pub fn scroll(&mut self, scroll: Scroll) {
- if self.last_mode.intersects(TermMode::MOUSE_MODE) {
- //TODE: MOUSE MODE
+ pub fn mouse_up(&mut self, e: &MouseButtonEvent, origin: Vector2F) {
+ let position = e.position.sub(origin);
+
+ if self.mouse_mode(e.shift) {
+ let point = mouse_point(position, self.cur_size, self.last_offset);
+
+ if let Some(bytes) = mouse_button_report(point, e, false, self.last_mode) {
+ self.pty_tx.notify(bytes);
+ }
+ } else {
+ // Seems pretty standard to automatically copy on mouse_up for terminals,
+ // so let's do that here
+ self.copy();
}
+ }
- self.events.push(InternalEvent::Scroll(scroll));
+ ///Scroll the terminal
+ pub fn scroll(&mut self, scroll: &ScrollWheelEvent, origin: Vector2F) {
+ if self.mouse_mode(false) {
+ //TODO: Currently this only sends the current scroll reports as they come in. Alacritty
+ //Sends the *entire* scroll delta on *every* scroll event, only resetting it when
+ //The scroll enters 'TouchPhase::Started'. Do I need to replicate this?
+ //This would be consistent with a scroll model based on 'distance from origin'...
+ let scroll_lines = (scroll.delta.y() / self.cur_size.line_height) as i32;
+ let point = mouse_point(scroll.position.sub(origin), self.cur_size, self.last_offset);
+
+ if let Some(scrolls) = scroll_report(point, scroll_lines as i32, scroll, self.last_mode)
+ {
+ for scroll in scrolls {
+ self.pty_tx.notify(scroll);
+ }
+ };
+ } else if self
+ .last_mode
+ .contains(TermMode::ALT_SCREEN | TermMode::ALTERNATE_SCROLL)
+ {
+ //TODO: See above TODO, also applies here.
+ let scroll_lines = ((scroll.delta.y() * ALACRITTY_SCROLL_MULTIPLIER)
+ / self.cur_size.line_height) as i32;
+
+ self.pty_tx.notify(alt_scroll(scroll_lines))
+ } else {
+ let scroll_lines = ((scroll.delta.y() * ALACRITTY_SCROLL_MULTIPLIER)
+ / self.cur_size.line_height) as i32;
+ if scroll_lines != 0 {
+ let scroll = Scroll::Delta(scroll_lines);
+ self.events.push(InternalEvent::Scroll(scroll));
+ }
+ }
}
}