diff options
-rw-r--r-- | src/event.rs | 4 | ||||
-rw-r--r-- | src/input.rs | 99 | ||||
-rw-r--r-- | src/term/mod.rs | 39 |
3 files changed, 92 insertions, 50 deletions
diff --git a/src/event.rs b/src/event.rs index 8c4107ca..770ac53e 100644 --- a/src/event.rs +++ b/src/event.rs @@ -148,6 +148,8 @@ pub struct Mouse { pub x: u32, pub y: u32, pub left_button_state: ElementState, + pub middle_button_state: ElementState, + pub right_button_state: ElementState, pub last_click_timestamp: Instant, pub click_state: ClickState, pub scroll_px: i32, @@ -164,6 +166,8 @@ impl Default for Mouse { y: 0, last_click_timestamp: Instant::now(), left_button_state: ElementState::Released, + middle_button_state: ElementState::Released, + right_button_state: ElementState::Released, click_state: ClickState::None, scroll_px: 0, line: Line(0), diff --git a/src/input.rs b/src/input.rs index ff1eb796..06fd5e5b 100644 --- a/src/input.rs +++ b/src/input.rs @@ -278,21 +278,33 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { }; self.ctx.mouse_mut().cell_side = cell_side; - if self.ctx.mouse_mut().left_button_state == ElementState::Pressed { - let report_mode = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_MOTION; - if 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().contains(mode::TermMode::MOUSE_MOTION) - // Only report motion when changing cells - && ( - prev_line != self.ctx.mouse_mut().line - || prev_col != self.ctx.mouse_mut().column - ) - { - self.mouse_report(32, ElementState::Pressed); + let report_mode = mode::TermMode::MOUSE_REPORT_CLICK; + let motion_mode = mode::TermMode::MOUSE_MOTION | mode::TermMode::MOUSE_DRAG; + if self.ctx.mouse_mut().left_button_state == ElementState::Pressed + && ( + modifiers.shift + || !self.ctx.terminal_mode().intersects(report_mode | 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 + 0, ElementState::Pressed); + } else if self.ctx.mouse_mut().middle_button_state == ElementState::Pressed { + self.mouse_report(32 + 1, ElementState::Pressed); + } else if self.ctx.mouse_mut().right_button_state == ElementState::Pressed { + self.mouse_report(32 + 2, ElementState::Pressed); + } else if self.ctx.terminal_mode().contains(mode::TermMode::MOUSE_MOTION) { + self.mouse_report(32 + 3, ElementState::Pressed); } } } @@ -330,7 +342,11 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { if self.ctx.terminal_mode().contains(mode::TermMode::SGR_MOUSE) { self.sgr_mouse_report(button, state); } else { - self.normal_mouse_report(button); + if let ElementState::Released = state { + self.normal_mouse_report(3); + } else { + self.normal_mouse_report(button); + } } } @@ -346,7 +362,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { } } - pub fn on_mouse_press(&mut self, modifiers: ModifiersState) { + pub fn on_mouse_press(&mut self, button: MouseButton, modifiers: ModifiersState) { let now = Instant::now(); let elapsed = self.ctx.mouse_mut().last_click_timestamp.elapsed(); self.ctx.mouse_mut().last_click_timestamp = now; @@ -362,9 +378,15 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { }, _ => { self.ctx.clear_selection(); - let report_modes = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_MOTION; + let report_modes = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_DRAG | mode::TermMode::MOUSE_MOTION; if !modifiers.shift && self.ctx.terminal_mode().intersects(report_modes) { - self.mouse_report(0, ElementState::Pressed); + match button { + MouseButton::Left => self.mouse_report(0, ElementState::Pressed), + MouseButton::Middle => self.mouse_report(1, ElementState::Pressed), + MouseButton::Right => self.mouse_report(2, ElementState::Pressed), + // Can't properly report more than three buttons. + MouseButton::Other(_) => (), + }; return; } @@ -373,11 +395,17 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { }; } - pub fn on_mouse_release(&mut self, modifiers: ModifiersState) { - let report_modes = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_MOTION; + pub fn on_mouse_release(&mut self, button: MouseButton, modifiers: ModifiersState) { + let report_modes = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_DRAG | mode::TermMode::MOUSE_MOTION; if !modifiers.shift && self.ctx.terminal_mode().intersects(report_modes) { - self.mouse_report(3, ElementState::Released); + match button { + MouseButton::Left => self.mouse_report(0, ElementState::Released), + MouseButton::Middle => self.mouse_report(1, ElementState::Released), + MouseButton::Right => self.mouse_report(2, ElementState::Released), + // Can't properly report more than three buttons. + MouseButton::Other(_) => (), + }; return; } @@ -385,7 +413,7 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { } pub fn on_mouse_wheel(&mut self, delta: MouseScrollDelta, phase: TouchPhase) { - let mouse_modes = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_MOTION | mode::TermMode::SGR_MOUSE; + let mouse_modes = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_DRAG | mode::TermMode::MOUSE_MOTION | mode::TermMode::SGR_MOUSE; if !self.ctx.terminal_mode().intersects(mouse_modes | mode::TermMode::ALT_SCREEN) { return; } @@ -466,17 +494,20 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { } pub fn mouse_input(&mut self, state: ElementState, button: MouseButton, modifiers: ModifiersState) { - if let MouseButton::Left = button { - let state = mem::replace(&mut self.ctx.mouse_mut().left_button_state, state); - if self.ctx.mouse_mut().left_button_state != state { - match self.ctx.mouse_mut().left_button_state { - ElementState::Pressed => { - self.on_mouse_press(modifiers); - }, - ElementState::Released => { - self.on_mouse_release(modifiers); - } - } + let button_state = match button { + MouseButton::Left => Some(mem::replace(&mut self.ctx.mouse_mut().left_button_state, state)), + MouseButton::Middle => Some(mem::replace(&mut self.ctx.mouse_mut().middle_button_state, state)), + MouseButton::Right => Some(mem::replace(&mut self.ctx.mouse_mut().right_button_state, state)), + // Can't properly report more than three buttons. + MouseButton::Other(_) => None, + }; + + if let Some(button_state) = button_state { + if button_state != state { + match state { + ElementState::Pressed => self.on_mouse_press(button, modifiers), + ElementState::Released => self.on_mouse_release(button, modifiers), + }; } } diff --git a/src/term/mod.rs b/src/term/mod.rs index 88e4b63c..5ba192ff 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -418,20 +418,21 @@ impl<'a> Iterator for RenderableCellsIter<'a> { pub mod mode { bitflags! { pub struct TermMode: u16 { - const SHOW_CURSOR = 0b0_0000_0000_0001; - const APP_CURSOR = 0b0_0000_0000_0010; - const APP_KEYPAD = 0b0_0000_0000_0100; - const MOUSE_REPORT_CLICK = 0b0_0000_0000_1000; - const BRACKETED_PASTE = 0b0_0000_0001_0000; - const SGR_MOUSE = 0b0_0000_0010_0000; - const MOUSE_MOTION = 0b0_0000_0100_0000; - const LINE_WRAP = 0b0_0000_1000_0000; - const LINE_FEED_NEW_LINE = 0b0_0001_0000_0000; - const ORIGIN = 0b0_0010_0000_0000; - const INSERT = 0b0_0100_0000_0000; - const FOCUS_IN_OUT = 0b0_1000_0000_0000; - const ALT_SCREEN = 0b1_0000_0000_0000; - const ANY = 0b1_1111_1111_1111; + const SHOW_CURSOR = 0b00_0000_0000_0001; + const APP_CURSOR = 0b00_0000_0000_0010; + const APP_KEYPAD = 0b00_0000_0000_0100; + const MOUSE_REPORT_CLICK = 0b00_0000_0000_1000; + const BRACKETED_PASTE = 0b00_0000_0001_0000; + const SGR_MOUSE = 0b00_0000_0010_0000; + const MOUSE_MOTION = 0b00_0000_0100_0000; + const LINE_WRAP = 0b00_0000_1000_0000; + const LINE_FEED_NEW_LINE = 0b00_0001_0000_0000; + const ORIGIN = 0b00_0010_0000_0000; + const INSERT = 0b00_0100_0000_0000; + const FOCUS_IN_OUT = 0b00_1000_0000_0000; + const ALT_SCREEN = 0b01_0000_0000_0000; + const MOUSE_DRAG = 0b10_0000_0000_0000; + const ANY = 0b11_1111_1111_1111; const NONE = 0; } } @@ -1832,7 +1833,10 @@ impl ansi::Handler for Term { self.mode.insert(mode::TermMode::MOUSE_REPORT_CLICK); self.set_mouse_cursor(MouseCursor::Arrow); }, - ansi::Mode::ReportCellMouseMotion | + ansi::Mode::ReportCellMouseMotion => { + self.mode.insert(mode::TermMode::MOUSE_DRAG); + self.set_mouse_cursor(MouseCursor::Arrow); + }, ansi::Mode::ReportAllMouseMotion => { self.mode.insert(mode::TermMode::MOUSE_MOTION); self.set_mouse_cursor(MouseCursor::Arrow); @@ -1869,7 +1873,10 @@ impl ansi::Handler for Term { self.mode.remove(mode::TermMode::MOUSE_REPORT_CLICK); self.set_mouse_cursor(MouseCursor::Text); }, - ansi::Mode::ReportCellMouseMotion | + ansi::Mode::ReportCellMouseMotion => { + self.mode.remove(mode::TermMode::MOUSE_DRAG); + self.set_mouse_cursor(MouseCursor::Text); + }, ansi::Mode::ReportAllMouseMotion => { self.mode.remove(mode::TermMode::MOUSE_MOTION); self.set_mouse_cursor(MouseCursor::Text); |