WIP
This commit is contained in:
parent
953857f8e3
commit
9a53da28bc
9 changed files with 413 additions and 377 deletions
|
@ -476,19 +476,14 @@ impl AppContext {
|
||||||
|
|
||||||
pub fn spawn_on_main<F, R>(
|
pub fn spawn_on_main<F, R>(
|
||||||
&self,
|
&self,
|
||||||
f: impl FnOnce(&mut MainThread<AppContext>) -> F + Send + 'static,
|
f: impl FnOnce(MainThread<AsyncAppContext>) -> F + Send + 'static,
|
||||||
) -> Task<R>
|
) -> Task<R>
|
||||||
where
|
where
|
||||||
F: Future<Output = R> + 'static,
|
F: Future<Output = R> + 'static,
|
||||||
R: Send + 'static,
|
R: Send + 'static,
|
||||||
{
|
{
|
||||||
let this = self.this.upgrade().unwrap();
|
let cx = self.to_async();
|
||||||
self.executor.spawn_on_main(move || {
|
self.executor.spawn_on_main(move || f(MainThread(cx)))
|
||||||
let cx = &mut *this.lock();
|
|
||||||
cx.update(|cx| {
|
|
||||||
f(unsafe { mem::transmute::<&mut AppContext, &mut MainThread<AppContext>>(cx) })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static) -> Task<R>
|
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static) -> Task<R>
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
AppContext, AsyncAppContext, Context, Effect, EntityId, EventEmitter, Handle, Reference,
|
AppContext, AsyncAppContext, Context, Effect, EntityId, EventEmitter, Handle, MainThread,
|
||||||
Subscription, Task, WeakHandle,
|
Reference, Subscription, Task, WeakHandle,
|
||||||
};
|
};
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use std::{any::TypeId, future::Future, marker::PhantomData};
|
use std::{
|
||||||
|
any::TypeId,
|
||||||
|
borrow::{Borrow, BorrowMut},
|
||||||
|
future::Future,
|
||||||
|
marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
#[derive(Deref, DerefMut)]
|
||||||
pub struct ModelContext<'a, T> {
|
pub struct ModelContext<'a, T> {
|
||||||
|
@ -174,6 +179,18 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||||
let this = self.weak_handle();
|
let this = self.weak_handle();
|
||||||
self.app.spawn(|cx| f(this, cx))
|
self.app.spawn(|cx| f(this, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn spawn_on_main<Fut, R>(
|
||||||
|
&self,
|
||||||
|
f: impl FnOnce(WeakHandle<T>, MainThread<AsyncAppContext>) -> Fut + Send + 'static,
|
||||||
|
) -> Task<R>
|
||||||
|
where
|
||||||
|
Fut: Future<Output = R> + 'static,
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
let this = self.weak_handle();
|
||||||
|
self.app.spawn_on_main(|cx| f(this, cx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> {
|
impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> {
|
||||||
|
@ -204,3 +221,15 @@ impl<'a, T: 'static> Context for ModelContext<'a, T> {
|
||||||
self.app.update_entity(handle, update)
|
self.app.update_entity(handle, update)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Borrow<AppContext> for ModelContext<'_, T> {
|
||||||
|
fn borrow(&self) -> &AppContext {
|
||||||
|
&self.app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> BorrowMut<AppContext> for ModelContext<'_, T> {
|
||||||
|
fn borrow_mut(&mut self) -> &mut AppContext {
|
||||||
|
&mut self.app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -203,6 +203,16 @@ impl Hsla {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl From<Hsla> for Rgba {
|
||||||
|
// fn from(value: Hsla) -> Self {
|
||||||
|
// let h = value.h;
|
||||||
|
// let s = value.s;
|
||||||
|
// let l = value.l;
|
||||||
|
|
||||||
|
// let c = (1 - |2L - 1|) X s
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
impl From<Rgba> for Hsla {
|
impl From<Rgba> for Hsla {
|
||||||
fn from(color: Rgba) -> Self {
|
fn from(color: Rgba) -> Self {
|
||||||
let r = color.r;
|
let r = color.r;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use derive_more::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
|
use derive_more::{Add, AddAssign, Div, DivAssign, Mul, Neg, Sub, SubAssign};
|
||||||
use refineable::Refineable;
|
use refineable::Refineable;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -131,7 +131,7 @@ impl<T: Clone + Default + Debug> Clone for Point<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Refineable, Default, Clone, Copy, PartialEq, Div, Hash)]
|
#[derive(Refineable, Default, Clone, Copy, PartialEq, Div, Hash, Serialize, Deserialize)]
|
||||||
#[refineable(debug)]
|
#[refineable(debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Size<T: Clone + Default + Debug> {
|
pub struct Size<T: Clone + Default + Debug> {
|
||||||
|
@ -660,8 +660,9 @@ impl<T> Copy for Corners<T> where T: Copy + Clone + Default + Debug {}
|
||||||
AddAssign,
|
AddAssign,
|
||||||
Sub,
|
Sub,
|
||||||
SubAssign,
|
SubAssign,
|
||||||
Div,
|
|
||||||
Neg,
|
Neg,
|
||||||
|
Div,
|
||||||
|
DivAssign,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
PartialOrd,
|
PartialOrd,
|
||||||
Serialize,
|
Serialize,
|
||||||
|
@ -670,6 +671,34 @@ impl<T> Copy for Corners<T> where T: Copy + Clone + Default + Debug {}
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Pixels(pub(crate) f32);
|
pub struct Pixels(pub(crate) f32);
|
||||||
|
|
||||||
|
impl std::ops::Div for Pixels {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
|
Self(self.0 / rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DivAssign for Pixels {
|
||||||
|
fn div_assign(&mut self, rhs: Self) {
|
||||||
|
self.0 /= rhs.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::RemAssign for Pixels {
|
||||||
|
fn rem_assign(&mut self, rhs: Self) {
|
||||||
|
self.0 %= rhs.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Rem for Pixels {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn rem(self, rhs: Self) -> Self {
|
||||||
|
Self(self.0 % rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<f32> for Pixels {
|
impl Mul<f32> for Pixels {
|
||||||
type Output = Pixels;
|
type Output = Pixels;
|
||||||
|
|
||||||
|
@ -703,6 +732,14 @@ impl MulAssign<f32> for Pixels {
|
||||||
impl Pixels {
|
impl Pixels {
|
||||||
pub const MAX: Pixels = Pixels(f32::MAX);
|
pub const MAX: Pixels = Pixels(f32::MAX);
|
||||||
|
|
||||||
|
pub fn as_usize(&self) -> usize {
|
||||||
|
self.0 as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_isize(&self) -> isize {
|
||||||
|
self.0 as isize
|
||||||
|
}
|
||||||
|
|
||||||
pub fn floor(&self) -> Self {
|
pub fn floor(&self) -> Self {
|
||||||
Self(self.0.floor())
|
Self(self.0.floor())
|
||||||
}
|
}
|
||||||
|
@ -714,6 +751,10 @@ impl Pixels {
|
||||||
pub fn scale(&self, factor: f32) -> ScaledPixels {
|
pub fn scale(&self, factor: f32) -> ScaledPixels {
|
||||||
ScaledPixels(self.0 * factor)
|
ScaledPixels(self.0 * factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pow(&self, exponent: f32) -> Self {
|
||||||
|
Self(self.0.powf(exponent))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<Pixels> for Pixels {
|
impl Mul<Pixels> for Pixels {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// todo!()
|
// todo!()
|
||||||
// use alacritty_terminal::{ansi::Color as AnsiColor, term::color::Rgb as AlacRgb};
|
use alacritty_terminal::term::color::Rgb as AlacRgb;
|
||||||
// use gpui2::color::Color;
|
// use gpui2::color::Color;
|
||||||
// use theme2::TerminalStyle;
|
// use theme2::TerminalStyle;
|
||||||
|
|
||||||
// ///Converts a 2, 8, or 24 bit color ANSI color to the GPUI equivalent
|
///Converts a 2, 8, or 24 bit color ANSI color to the GPUI equivalent
|
||||||
// pub fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color {
|
// pub fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color {
|
||||||
// match alac_color {
|
// match alac_color {
|
||||||
// //Named and theme defined colors
|
// //Named and theme defined colors
|
||||||
|
@ -45,9 +45,10 @@
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// ///Converts an 8 bit ANSI color to it's GPUI equivalent.
|
/// TODO: Move this
|
||||||
// ///Accepts usize for compatibility with the alacritty::Colors interface,
|
///Converts an 8 bit ANSI color to it's GPUI equivalent.
|
||||||
// ///Other than that use case, should only be called with values in the [0,255] range
|
///Accepts usize for compatibility with the alacritty::Colors interface,
|
||||||
|
///Other than that use case, should only be called with values in the [0,255] range
|
||||||
// pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color {
|
// pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color {
|
||||||
// match index {
|
// match index {
|
||||||
// //0-15 are the same as the named colors above
|
// //0-15 are the same as the named colors above
|
||||||
|
@ -96,14 +97,14 @@
|
||||||
// _ => Color::new(0, 0, 0, 255),
|
// _ => Color::new(0, 0, 0, 255),
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// ///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube
|
///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube
|
||||||
// ///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit).
|
///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit).
|
||||||
// ///
|
///
|
||||||
// ///Wikipedia gives a formula for calculating the index for a given color:
|
///Wikipedia gives a formula for calculating the index for a given color:
|
||||||
// ///
|
///
|
||||||
// ///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
|
///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
|
||||||
// ///
|
///
|
||||||
// ///This function does the reverse, calculating the r, g, and b components from a given index.
|
///This function does the reverse, calculating the r, g, and b components from a given index.
|
||||||
// fn rgb_for_index(i: &u8) -> (u8, u8, u8) {
|
// fn rgb_for_index(i: &u8) -> (u8, u8, u8) {
|
||||||
// debug_assert!((&16..=&231).contains(&i));
|
// debug_assert!((&16..=&231).contains(&i));
|
||||||
// let i = i - 16;
|
// let i = i - 16;
|
||||||
|
@ -112,11 +113,16 @@
|
||||||
// let b = (i % 36) % 6;
|
// let b = (i % 36) % 6;
|
||||||
// (r, g, b)
|
// (r, g, b)
|
||||||
// }
|
// }
|
||||||
|
use gpui2::Rgba;
|
||||||
|
|
||||||
// //Convenience method to convert from a GPUI color to an alacritty Rgb
|
//Convenience method to convert from a GPUI color to an alacritty Rgb
|
||||||
// pub fn to_alac_rgb(color: Color) -> AlacRgb {
|
pub fn to_alac_rgb(color: impl Into<Rgba>) -> AlacRgb {
|
||||||
// AlacRgb::new(color.r, color.g, color.g)
|
let color = color.into();
|
||||||
// }
|
let r = ((color.r * color.a) * 255.) as u8;
|
||||||
|
let g = ((color.g * color.a) * 255.) as u8;
|
||||||
|
let b = ((color.b * color.a) * 255.) as u8;
|
||||||
|
AlacRgb::new(r, g, b)
|
||||||
|
}
|
||||||
|
|
||||||
// #[cfg(test)]
|
// #[cfg(test)]
|
||||||
// mod tests {
|
// mod tests {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/// The mappings defined in this file where created from reading the alacritty source
|
/// The mappings defined in this file where created from reading the alacritty source
|
||||||
use alacritty_terminal::term::TermMode;
|
use alacritty_terminal::term::TermMode;
|
||||||
use gpui2::keymap_matcher::Keystroke;
|
use gpui2::Keystroke;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Modifiers {
|
enum AlacModifiers {
|
||||||
None,
|
None,
|
||||||
Alt,
|
Alt,
|
||||||
Ctrl,
|
Ctrl,
|
||||||
|
@ -12,179 +12,184 @@ pub enum Modifiers {
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Modifiers {
|
impl AlacModifiers {
|
||||||
fn new(ks: &Keystroke) -> Self {
|
fn new(ks: &Keystroke) -> Self {
|
||||||
match (ks.alt, ks.ctrl, ks.shift, ks.cmd) {
|
match (
|
||||||
(false, false, false, false) => Modifiers::None,
|
ks.modifiers.alt,
|
||||||
(true, false, false, false) => Modifiers::Alt,
|
ks.modifiers.control,
|
||||||
(false, true, false, false) => Modifiers::Ctrl,
|
ks.modifiers.shift,
|
||||||
(false, false, true, false) => Modifiers::Shift,
|
ks.modifiers.command,
|
||||||
(false, true, true, false) => Modifiers::CtrlShift,
|
) {
|
||||||
_ => Modifiers::Other,
|
(false, false, false, false) => AlacModifiers::None,
|
||||||
|
(true, false, false, false) => AlacModifiers::Alt,
|
||||||
|
(false, true, false, false) => AlacModifiers::Ctrl,
|
||||||
|
(false, false, true, false) => AlacModifiers::Shift,
|
||||||
|
(false, true, true, false) => AlacModifiers::CtrlShift,
|
||||||
|
_ => AlacModifiers::Other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn any(&self) -> bool {
|
fn any(&self) -> bool {
|
||||||
match &self {
|
match &self {
|
||||||
Modifiers::None => false,
|
AlacModifiers::None => false,
|
||||||
Modifiers::Alt => true,
|
AlacModifiers::Alt => true,
|
||||||
Modifiers::Ctrl => true,
|
AlacModifiers::Ctrl => true,
|
||||||
Modifiers::Shift => true,
|
AlacModifiers::Shift => true,
|
||||||
Modifiers::CtrlShift => true,
|
AlacModifiers::CtrlShift => true,
|
||||||
Modifiers::Other => true,
|
AlacModifiers::Other => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) -> Option<String> {
|
pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) -> Option<String> {
|
||||||
let modifiers = Modifiers::new(keystroke);
|
let modifiers = AlacModifiers::new(keystroke);
|
||||||
|
|
||||||
// Manual Bindings including modifiers
|
// Manual Bindings including modifiers
|
||||||
let manual_esc_str = match (keystroke.key.as_ref(), &modifiers) {
|
let manual_esc_str = match (keystroke.key.as_ref(), &modifiers) {
|
||||||
//Basic special keys
|
//Basic special keys
|
||||||
("tab", Modifiers::None) => Some("\x09".to_string()),
|
("tab", AlacModifiers::None) => Some("\x09".to_string()),
|
||||||
("escape", Modifiers::None) => Some("\x1b".to_string()),
|
("escape", AlacModifiers::None) => Some("\x1b".to_string()),
|
||||||
("enter", Modifiers::None) => Some("\x0d".to_string()),
|
("enter", AlacModifiers::None) => Some("\x0d".to_string()),
|
||||||
("enter", Modifiers::Shift) => Some("\x0d".to_string()),
|
("enter", AlacModifiers::Shift) => Some("\x0d".to_string()),
|
||||||
("backspace", Modifiers::None) => Some("\x7f".to_string()),
|
("backspace", AlacModifiers::None) => Some("\x7f".to_string()),
|
||||||
//Interesting escape codes
|
//Interesting escape codes
|
||||||
("tab", Modifiers::Shift) => Some("\x1b[Z".to_string()),
|
("tab", AlacModifiers::Shift) => Some("\x1b[Z".to_string()),
|
||||||
("backspace", Modifiers::Alt) => Some("\x1b\x7f".to_string()),
|
("backspace", AlacModifiers::Alt) => Some("\x1b\x7f".to_string()),
|
||||||
("backspace", Modifiers::Shift) => Some("\x7f".to_string()),
|
("backspace", AlacModifiers::Shift) => Some("\x7f".to_string()),
|
||||||
("home", Modifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
("home", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
||||||
Some("\x1b[1;2H".to_string())
|
Some("\x1b[1;2H".to_string())
|
||||||
}
|
}
|
||||||
("end", Modifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
("end", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
||||||
Some("\x1b[1;2F".to_string())
|
Some("\x1b[1;2F".to_string())
|
||||||
}
|
}
|
||||||
("pageup", Modifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
("pageup", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
||||||
Some("\x1b[5;2~".to_string())
|
Some("\x1b[5;2~".to_string())
|
||||||
}
|
}
|
||||||
("pagedown", Modifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
("pagedown", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => {
|
||||||
Some("\x1b[6;2~".to_string())
|
Some("\x1b[6;2~".to_string())
|
||||||
}
|
}
|
||||||
("home", Modifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
("home", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1bOH".to_string())
|
Some("\x1bOH".to_string())
|
||||||
}
|
}
|
||||||
("home", Modifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
("home", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1b[H".to_string())
|
Some("\x1b[H".to_string())
|
||||||
}
|
}
|
||||||
("end", Modifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
("end", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1bOF".to_string())
|
Some("\x1bOF".to_string())
|
||||||
}
|
}
|
||||||
("end", Modifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
("end", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1b[F".to_string())
|
Some("\x1b[F".to_string())
|
||||||
}
|
}
|
||||||
("up", Modifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
("up", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1bOA".to_string())
|
Some("\x1bOA".to_string())
|
||||||
}
|
}
|
||||||
("up", Modifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
("up", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1b[A".to_string())
|
Some("\x1b[A".to_string())
|
||||||
}
|
}
|
||||||
("down", Modifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
("down", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1bOB".to_string())
|
Some("\x1bOB".to_string())
|
||||||
}
|
}
|
||||||
("down", Modifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
("down", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1b[B".to_string())
|
Some("\x1b[B".to_string())
|
||||||
}
|
}
|
||||||
("right", Modifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
("right", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1bOC".to_string())
|
Some("\x1bOC".to_string())
|
||||||
}
|
}
|
||||||
("right", Modifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
("right", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1b[C".to_string())
|
Some("\x1b[C".to_string())
|
||||||
}
|
}
|
||||||
("left", Modifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
("left", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1bOD".to_string())
|
Some("\x1bOD".to_string())
|
||||||
}
|
}
|
||||||
("left", Modifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
("left", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => {
|
||||||
Some("\x1b[D".to_string())
|
Some("\x1b[D".to_string())
|
||||||
}
|
}
|
||||||
("back", Modifiers::None) => Some("\x7f".to_string()),
|
("back", AlacModifiers::None) => Some("\x7f".to_string()),
|
||||||
("insert", Modifiers::None) => Some("\x1b[2~".to_string()),
|
("insert", AlacModifiers::None) => Some("\x1b[2~".to_string()),
|
||||||
("delete", Modifiers::None) => Some("\x1b[3~".to_string()),
|
("delete", AlacModifiers::None) => Some("\x1b[3~".to_string()),
|
||||||
("pageup", Modifiers::None) => Some("\x1b[5~".to_string()),
|
("pageup", AlacModifiers::None) => Some("\x1b[5~".to_string()),
|
||||||
("pagedown", Modifiers::None) => Some("\x1b[6~".to_string()),
|
("pagedown", AlacModifiers::None) => Some("\x1b[6~".to_string()),
|
||||||
("f1", Modifiers::None) => Some("\x1bOP".to_string()),
|
("f1", AlacModifiers::None) => Some("\x1bOP".to_string()),
|
||||||
("f2", Modifiers::None) => Some("\x1bOQ".to_string()),
|
("f2", AlacModifiers::None) => Some("\x1bOQ".to_string()),
|
||||||
("f3", Modifiers::None) => Some("\x1bOR".to_string()),
|
("f3", AlacModifiers::None) => Some("\x1bOR".to_string()),
|
||||||
("f4", Modifiers::None) => Some("\x1bOS".to_string()),
|
("f4", AlacModifiers::None) => Some("\x1bOS".to_string()),
|
||||||
("f5", Modifiers::None) => Some("\x1b[15~".to_string()),
|
("f5", AlacModifiers::None) => Some("\x1b[15~".to_string()),
|
||||||
("f6", Modifiers::None) => Some("\x1b[17~".to_string()),
|
("f6", AlacModifiers::None) => Some("\x1b[17~".to_string()),
|
||||||
("f7", Modifiers::None) => Some("\x1b[18~".to_string()),
|
("f7", AlacModifiers::None) => Some("\x1b[18~".to_string()),
|
||||||
("f8", Modifiers::None) => Some("\x1b[19~".to_string()),
|
("f8", AlacModifiers::None) => Some("\x1b[19~".to_string()),
|
||||||
("f9", Modifiers::None) => Some("\x1b[20~".to_string()),
|
("f9", AlacModifiers::None) => Some("\x1b[20~".to_string()),
|
||||||
("f10", Modifiers::None) => Some("\x1b[21~".to_string()),
|
("f10", AlacModifiers::None) => Some("\x1b[21~".to_string()),
|
||||||
("f11", Modifiers::None) => Some("\x1b[23~".to_string()),
|
("f11", AlacModifiers::None) => Some("\x1b[23~".to_string()),
|
||||||
("f12", Modifiers::None) => Some("\x1b[24~".to_string()),
|
("f12", AlacModifiers::None) => Some("\x1b[24~".to_string()),
|
||||||
("f13", Modifiers::None) => Some("\x1b[25~".to_string()),
|
("f13", AlacModifiers::None) => Some("\x1b[25~".to_string()),
|
||||||
("f14", Modifiers::None) => Some("\x1b[26~".to_string()),
|
("f14", AlacModifiers::None) => Some("\x1b[26~".to_string()),
|
||||||
("f15", Modifiers::None) => Some("\x1b[28~".to_string()),
|
("f15", AlacModifiers::None) => Some("\x1b[28~".to_string()),
|
||||||
("f16", Modifiers::None) => Some("\x1b[29~".to_string()),
|
("f16", AlacModifiers::None) => Some("\x1b[29~".to_string()),
|
||||||
("f17", Modifiers::None) => Some("\x1b[31~".to_string()),
|
("f17", AlacModifiers::None) => Some("\x1b[31~".to_string()),
|
||||||
("f18", Modifiers::None) => Some("\x1b[32~".to_string()),
|
("f18", AlacModifiers::None) => Some("\x1b[32~".to_string()),
|
||||||
("f19", Modifiers::None) => Some("\x1b[33~".to_string()),
|
("f19", AlacModifiers::None) => Some("\x1b[33~".to_string()),
|
||||||
("f20", Modifiers::None) => Some("\x1b[34~".to_string()),
|
("f20", AlacModifiers::None) => Some("\x1b[34~".to_string()),
|
||||||
// NumpadEnter, Action::Esc("\n".into());
|
// NumpadEnter, Action::Esc("\n".into());
|
||||||
//Mappings for caret notation keys
|
//Mappings for caret notation keys
|
||||||
("a", Modifiers::Ctrl) => Some("\x01".to_string()), //1
|
("a", AlacModifiers::Ctrl) => Some("\x01".to_string()), //1
|
||||||
("A", Modifiers::CtrlShift) => Some("\x01".to_string()), //1
|
("A", AlacModifiers::CtrlShift) => Some("\x01".to_string()), //1
|
||||||
("b", Modifiers::Ctrl) => Some("\x02".to_string()), //2
|
("b", AlacModifiers::Ctrl) => Some("\x02".to_string()), //2
|
||||||
("B", Modifiers::CtrlShift) => Some("\x02".to_string()), //2
|
("B", AlacModifiers::CtrlShift) => Some("\x02".to_string()), //2
|
||||||
("c", Modifiers::Ctrl) => Some("\x03".to_string()), //3
|
("c", AlacModifiers::Ctrl) => Some("\x03".to_string()), //3
|
||||||
("C", Modifiers::CtrlShift) => Some("\x03".to_string()), //3
|
("C", AlacModifiers::CtrlShift) => Some("\x03".to_string()), //3
|
||||||
("d", Modifiers::Ctrl) => Some("\x04".to_string()), //4
|
("d", AlacModifiers::Ctrl) => Some("\x04".to_string()), //4
|
||||||
("D", Modifiers::CtrlShift) => Some("\x04".to_string()), //4
|
("D", AlacModifiers::CtrlShift) => Some("\x04".to_string()), //4
|
||||||
("e", Modifiers::Ctrl) => Some("\x05".to_string()), //5
|
("e", AlacModifiers::Ctrl) => Some("\x05".to_string()), //5
|
||||||
("E", Modifiers::CtrlShift) => Some("\x05".to_string()), //5
|
("E", AlacModifiers::CtrlShift) => Some("\x05".to_string()), //5
|
||||||
("f", Modifiers::Ctrl) => Some("\x06".to_string()), //6
|
("f", AlacModifiers::Ctrl) => Some("\x06".to_string()), //6
|
||||||
("F", Modifiers::CtrlShift) => Some("\x06".to_string()), //6
|
("F", AlacModifiers::CtrlShift) => Some("\x06".to_string()), //6
|
||||||
("g", Modifiers::Ctrl) => Some("\x07".to_string()), //7
|
("g", AlacModifiers::Ctrl) => Some("\x07".to_string()), //7
|
||||||
("G", Modifiers::CtrlShift) => Some("\x07".to_string()), //7
|
("G", AlacModifiers::CtrlShift) => Some("\x07".to_string()), //7
|
||||||
("h", Modifiers::Ctrl) => Some("\x08".to_string()), //8
|
("h", AlacModifiers::Ctrl) => Some("\x08".to_string()), //8
|
||||||
("H", Modifiers::CtrlShift) => Some("\x08".to_string()), //8
|
("H", AlacModifiers::CtrlShift) => Some("\x08".to_string()), //8
|
||||||
("i", Modifiers::Ctrl) => Some("\x09".to_string()), //9
|
("i", AlacModifiers::Ctrl) => Some("\x09".to_string()), //9
|
||||||
("I", Modifiers::CtrlShift) => Some("\x09".to_string()), //9
|
("I", AlacModifiers::CtrlShift) => Some("\x09".to_string()), //9
|
||||||
("j", Modifiers::Ctrl) => Some("\x0a".to_string()), //10
|
("j", AlacModifiers::Ctrl) => Some("\x0a".to_string()), //10
|
||||||
("J", Modifiers::CtrlShift) => Some("\x0a".to_string()), //10
|
("J", AlacModifiers::CtrlShift) => Some("\x0a".to_string()), //10
|
||||||
("k", Modifiers::Ctrl) => Some("\x0b".to_string()), //11
|
("k", AlacModifiers::Ctrl) => Some("\x0b".to_string()), //11
|
||||||
("K", Modifiers::CtrlShift) => Some("\x0b".to_string()), //11
|
("K", AlacModifiers::CtrlShift) => Some("\x0b".to_string()), //11
|
||||||
("l", Modifiers::Ctrl) => Some("\x0c".to_string()), //12
|
("l", AlacModifiers::Ctrl) => Some("\x0c".to_string()), //12
|
||||||
("L", Modifiers::CtrlShift) => Some("\x0c".to_string()), //12
|
("L", AlacModifiers::CtrlShift) => Some("\x0c".to_string()), //12
|
||||||
("m", Modifiers::Ctrl) => Some("\x0d".to_string()), //13
|
("m", AlacModifiers::Ctrl) => Some("\x0d".to_string()), //13
|
||||||
("M", Modifiers::CtrlShift) => Some("\x0d".to_string()), //13
|
("M", AlacModifiers::CtrlShift) => Some("\x0d".to_string()), //13
|
||||||
("n", Modifiers::Ctrl) => Some("\x0e".to_string()), //14
|
("n", AlacModifiers::Ctrl) => Some("\x0e".to_string()), //14
|
||||||
("N", Modifiers::CtrlShift) => Some("\x0e".to_string()), //14
|
("N", AlacModifiers::CtrlShift) => Some("\x0e".to_string()), //14
|
||||||
("o", Modifiers::Ctrl) => Some("\x0f".to_string()), //15
|
("o", AlacModifiers::Ctrl) => Some("\x0f".to_string()), //15
|
||||||
("O", Modifiers::CtrlShift) => Some("\x0f".to_string()), //15
|
("O", AlacModifiers::CtrlShift) => Some("\x0f".to_string()), //15
|
||||||
("p", Modifiers::Ctrl) => Some("\x10".to_string()), //16
|
("p", AlacModifiers::Ctrl) => Some("\x10".to_string()), //16
|
||||||
("P", Modifiers::CtrlShift) => Some("\x10".to_string()), //16
|
("P", AlacModifiers::CtrlShift) => Some("\x10".to_string()), //16
|
||||||
("q", Modifiers::Ctrl) => Some("\x11".to_string()), //17
|
("q", AlacModifiers::Ctrl) => Some("\x11".to_string()), //17
|
||||||
("Q", Modifiers::CtrlShift) => Some("\x11".to_string()), //17
|
("Q", AlacModifiers::CtrlShift) => Some("\x11".to_string()), //17
|
||||||
("r", Modifiers::Ctrl) => Some("\x12".to_string()), //18
|
("r", AlacModifiers::Ctrl) => Some("\x12".to_string()), //18
|
||||||
("R", Modifiers::CtrlShift) => Some("\x12".to_string()), //18
|
("R", AlacModifiers::CtrlShift) => Some("\x12".to_string()), //18
|
||||||
("s", Modifiers::Ctrl) => Some("\x13".to_string()), //19
|
("s", AlacModifiers::Ctrl) => Some("\x13".to_string()), //19
|
||||||
("S", Modifiers::CtrlShift) => Some("\x13".to_string()), //19
|
("S", AlacModifiers::CtrlShift) => Some("\x13".to_string()), //19
|
||||||
("t", Modifiers::Ctrl) => Some("\x14".to_string()), //20
|
("t", AlacModifiers::Ctrl) => Some("\x14".to_string()), //20
|
||||||
("T", Modifiers::CtrlShift) => Some("\x14".to_string()), //20
|
("T", AlacModifiers::CtrlShift) => Some("\x14".to_string()), //20
|
||||||
("u", Modifiers::Ctrl) => Some("\x15".to_string()), //21
|
("u", AlacModifiers::Ctrl) => Some("\x15".to_string()), //21
|
||||||
("U", Modifiers::CtrlShift) => Some("\x15".to_string()), //21
|
("U", AlacModifiers::CtrlShift) => Some("\x15".to_string()), //21
|
||||||
("v", Modifiers::Ctrl) => Some("\x16".to_string()), //22
|
("v", AlacModifiers::Ctrl) => Some("\x16".to_string()), //22
|
||||||
("V", Modifiers::CtrlShift) => Some("\x16".to_string()), //22
|
("V", AlacModifiers::CtrlShift) => Some("\x16".to_string()), //22
|
||||||
("w", Modifiers::Ctrl) => Some("\x17".to_string()), //23
|
("w", AlacModifiers::Ctrl) => Some("\x17".to_string()), //23
|
||||||
("W", Modifiers::CtrlShift) => Some("\x17".to_string()), //23
|
("W", AlacModifiers::CtrlShift) => Some("\x17".to_string()), //23
|
||||||
("x", Modifiers::Ctrl) => Some("\x18".to_string()), //24
|
("x", AlacModifiers::Ctrl) => Some("\x18".to_string()), //24
|
||||||
("X", Modifiers::CtrlShift) => Some("\x18".to_string()), //24
|
("X", AlacModifiers::CtrlShift) => Some("\x18".to_string()), //24
|
||||||
("y", Modifiers::Ctrl) => Some("\x19".to_string()), //25
|
("y", AlacModifiers::Ctrl) => Some("\x19".to_string()), //25
|
||||||
("Y", Modifiers::CtrlShift) => Some("\x19".to_string()), //25
|
("Y", AlacModifiers::CtrlShift) => Some("\x19".to_string()), //25
|
||||||
("z", Modifiers::Ctrl) => Some("\x1a".to_string()), //26
|
("z", AlacModifiers::Ctrl) => Some("\x1a".to_string()), //26
|
||||||
("Z", Modifiers::CtrlShift) => Some("\x1a".to_string()), //26
|
("Z", AlacModifiers::CtrlShift) => Some("\x1a".to_string()), //26
|
||||||
("@", Modifiers::Ctrl) => Some("\x00".to_string()), //0
|
("@", AlacModifiers::Ctrl) => Some("\x00".to_string()), //0
|
||||||
("[", Modifiers::Ctrl) => Some("\x1b".to_string()), //27
|
("[", AlacModifiers::Ctrl) => Some("\x1b".to_string()), //27
|
||||||
("\\", Modifiers::Ctrl) => Some("\x1c".to_string()), //28
|
("\\", AlacModifiers::Ctrl) => Some("\x1c".to_string()), //28
|
||||||
("]", Modifiers::Ctrl) => Some("\x1d".to_string()), //29
|
("]", AlacModifiers::Ctrl) => Some("\x1d".to_string()), //29
|
||||||
("^", Modifiers::Ctrl) => Some("\x1e".to_string()), //30
|
("^", AlacModifiers::Ctrl) => Some("\x1e".to_string()), //30
|
||||||
("_", Modifiers::Ctrl) => Some("\x1f".to_string()), //31
|
("_", AlacModifiers::Ctrl) => Some("\x1f".to_string()), //31
|
||||||
("?", Modifiers::Ctrl) => Some("\x7f".to_string()), //127
|
("?", AlacModifiers::Ctrl) => Some("\x7f".to_string()), //127
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if manual_esc_str.is_some() {
|
if manual_esc_str.is_some() {
|
||||||
|
@ -232,8 +237,8 @@ pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let alt_meta_binding = if alt_is_meta && modifiers == Modifiers::Alt && keystroke.key.is_ascii()
|
let alt_meta_binding =
|
||||||
{
|
if alt_is_meta && modifiers == AlacModifiers::Alt && keystroke.key.is_ascii() {
|
||||||
Some(format!("\x1b{}", keystroke.key))
|
Some(format!("\x1b{}", keystroke.key))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -259,13 +264,13 @@ pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) ->
|
||||||
/// from: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
|
/// from: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
|
||||||
fn modifier_code(keystroke: &Keystroke) -> u32 {
|
fn modifier_code(keystroke: &Keystroke) -> u32 {
|
||||||
let mut modifier_code = 0;
|
let mut modifier_code = 0;
|
||||||
if keystroke.shift {
|
if keystroke.modifiers.shift {
|
||||||
modifier_code |= 1;
|
modifier_code |= 1;
|
||||||
}
|
}
|
||||||
if keystroke.alt {
|
if keystroke.modifiers.alt {
|
||||||
modifier_code |= 1 << 1;
|
modifier_code |= 1 << 1;
|
||||||
}
|
}
|
||||||
if keystroke.ctrl {
|
if keystroke.modifiers.control {
|
||||||
modifier_code |= 1 << 2;
|
modifier_code |= 1 << 2;
|
||||||
}
|
}
|
||||||
modifier_code + 1
|
modifier_code + 1
|
||||||
|
@ -273,7 +278,7 @@ fn modifier_code(keystroke: &Keystroke) -> u32 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use gpui2::keymap_matcher::Keystroke;
|
use gpui2::Modifiers;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -327,11 +332,13 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_plain_inputs() {
|
fn test_plain_inputs() {
|
||||||
let ks = Keystroke {
|
let ks = Keystroke {
|
||||||
ctrl: false,
|
modifiers: Modifiers {
|
||||||
|
control: false,
|
||||||
alt: false,
|
alt: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
cmd: false,
|
command: false,
|
||||||
function: false,
|
function: false,
|
||||||
|
},
|
||||||
key: "🖖🏻".to_string(), //2 char string
|
key: "🖖🏻".to_string(), //2 char string
|
||||||
ime_key: None,
|
ime_key: None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,52 +1,15 @@
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{self, max, min};
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
|
||||||
use alacritty_terminal::grid::Dimensions;
|
use alacritty_terminal::grid::Dimensions;
|
||||||
/// Most of the code, and specifically the constants, in this are copied from Alacritty,
|
/// Most of the code, and specifically the constants, in this are copied from Alacritty,
|
||||||
/// with modifications for our circumstances
|
/// with modifications for our circumstances
|
||||||
use alacritty_terminal::index::{Column as GridCol, Line as GridLine, Point, Side};
|
use alacritty_terminal::index::{Column as GridCol, Line as GridLine, Point as AlacPoint, Side};
|
||||||
use alacritty_terminal::term::TermMode;
|
use alacritty_terminal::term::TermMode;
|
||||||
use gpui2::platform;
|
use gpui2::{px, Modifiers, MouseButton, MouseMoveEvent, Pixels, Point, ScrollWheelEvent};
|
||||||
use gpui2::scene::MouseScrollWheel;
|
|
||||||
use gpui2::{
|
|
||||||
geometry::vector::Vector2F,
|
|
||||||
platform::{MouseButtonEvent, MouseMovedEvent, ScrollWheelEvent},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::TerminalSize;
|
use crate::TerminalSize;
|
||||||
|
|
||||||
struct Modifiers {
|
|
||||||
ctrl: bool,
|
|
||||||
shift: bool,
|
|
||||||
alt: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Modifiers {
|
|
||||||
fn from_moved(e: &MouseMovedEvent) -> Self {
|
|
||||||
Modifiers {
|
|
||||||
ctrl: e.ctrl,
|
|
||||||
shift: e.shift,
|
|
||||||
alt: e.alt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_button(e: &MouseButtonEvent) -> Self {
|
|
||||||
Modifiers {
|
|
||||||
ctrl: e.ctrl,
|
|
||||||
shift: e.shift,
|
|
||||||
alt: e.alt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_scroll(scroll: &ScrollWheelEvent) -> Self {
|
|
||||||
Modifiers {
|
|
||||||
ctrl: scroll.ctrl,
|
|
||||||
shift: scroll.shift,
|
|
||||||
alt: scroll.alt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MouseFormat {
|
enum MouseFormat {
|
||||||
SGR,
|
SGR,
|
||||||
Normal(bool),
|
Normal(bool),
|
||||||
|
@ -65,7 +28,7 @@ impl MouseFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum MouseButton {
|
enum AlacMouseButton {
|
||||||
LeftButton = 0,
|
LeftButton = 0,
|
||||||
MiddleButton = 1,
|
MiddleButton = 1,
|
||||||
RightButton = 2,
|
RightButton = 2,
|
||||||
|
@ -78,56 +41,61 @@ enum MouseButton {
|
||||||
Other = 99,
|
Other = 99,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MouseButton {
|
impl AlacMouseButton {
|
||||||
fn from_move(e: &MouseMovedEvent) -> Self {
|
fn from_move(e: &MouseMoveEvent) -> Self {
|
||||||
match e.pressed_button {
|
match e.pressed_button {
|
||||||
Some(b) => match b {
|
Some(b) => match b {
|
||||||
platform::MouseButton::Left => MouseButton::LeftMove,
|
gpui2::MouseButton::Left => AlacMouseButton::LeftMove,
|
||||||
platform::MouseButton::Middle => MouseButton::MiddleMove,
|
gpui2::MouseButton::Middle => AlacMouseButton::MiddleMove,
|
||||||
platform::MouseButton::Right => MouseButton::RightMove,
|
gpui2::MouseButton::Right => AlacMouseButton::RightMove,
|
||||||
platform::MouseButton::Navigate(_) => MouseButton::Other,
|
gpui2::MouseButton::Navigate(_) => AlacMouseButton::Other,
|
||||||
},
|
},
|
||||||
None => MouseButton::NoneMove,
|
None => AlacMouseButton::NoneMove,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_button(e: &MouseButtonEvent) -> Self {
|
fn from_button(e: MouseButton) -> Self {
|
||||||
match e.button {
|
match e {
|
||||||
platform::MouseButton::Left => MouseButton::LeftButton,
|
gpui2::MouseButton::Left => AlacMouseButton::LeftButton,
|
||||||
platform::MouseButton::Right => MouseButton::MiddleButton,
|
gpui2::MouseButton::Right => AlacMouseButton::MiddleButton,
|
||||||
platform::MouseButton::Middle => MouseButton::RightButton,
|
gpui2::MouseButton::Middle => AlacMouseButton::RightButton,
|
||||||
platform::MouseButton::Navigate(_) => MouseButton::Other,
|
gpui2::MouseButton::Navigate(_) => AlacMouseButton::Other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_scroll(e: &ScrollWheelEvent) -> Self {
|
fn from_scroll(e: &ScrollWheelEvent) -> Self {
|
||||||
if e.delta.raw().y() > 0. {
|
let is_positive = match e.delta {
|
||||||
MouseButton::ScrollUp
|
gpui2::ScrollDelta::Pixels(pixels) => pixels.y > px(0.),
|
||||||
|
gpui2::ScrollDelta::Lines(lines) => lines.y > 0.,
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_positive {
|
||||||
|
AlacMouseButton::ScrollUp
|
||||||
} else {
|
} else {
|
||||||
MouseButton::ScrollDown
|
AlacMouseButton::ScrollDown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_other(&self) -> bool {
|
fn is_other(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
MouseButton::Other => true,
|
AlacMouseButton::Other => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll_report(
|
pub fn scroll_report(
|
||||||
point: Point,
|
point: AlacPoint,
|
||||||
scroll_lines: i32,
|
scroll_lines: i32,
|
||||||
e: &MouseScrollWheel,
|
e: &ScrollWheelEvent,
|
||||||
mode: TermMode,
|
mode: TermMode,
|
||||||
) -> Option<impl Iterator<Item = Vec<u8>>> {
|
) -> Option<impl Iterator<Item = Vec<u8>>> {
|
||||||
if mode.intersects(TermMode::MOUSE_MODE) {
|
if mode.intersects(TermMode::MOUSE_MODE) {
|
||||||
mouse_report(
|
mouse_report(
|
||||||
point,
|
point,
|
||||||
MouseButton::from_scroll(e),
|
AlacMouseButton::from_scroll(e),
|
||||||
true,
|
true,
|
||||||
Modifiers::from_scroll(e),
|
e.modifiers,
|
||||||
MouseFormat::from_mode(mode),
|
MouseFormat::from_mode(mode),
|
||||||
)
|
)
|
||||||
.map(|report| repeat(report).take(max(scroll_lines, 1) as usize))
|
.map(|report| repeat(report).take(max(scroll_lines, 1) as usize))
|
||||||
|
@ -149,18 +117,19 @@ pub fn alt_scroll(scroll_lines: i32) -> Vec<u8> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_button_report(
|
pub fn mouse_button_report(
|
||||||
point: Point,
|
point: AlacPoint,
|
||||||
e: &MouseButtonEvent,
|
button: gpui2::MouseButton,
|
||||||
|
modifiers: Modifiers,
|
||||||
pressed: bool,
|
pressed: bool,
|
||||||
mode: TermMode,
|
mode: TermMode,
|
||||||
) -> Option<Vec<u8>> {
|
) -> Option<Vec<u8>> {
|
||||||
let button = MouseButton::from_button(e);
|
let button = AlacMouseButton::from_button(button);
|
||||||
if !button.is_other() && mode.intersects(TermMode::MOUSE_MODE) {
|
if !button.is_other() && mode.intersects(TermMode::MOUSE_MODE) {
|
||||||
mouse_report(
|
mouse_report(
|
||||||
point,
|
point,
|
||||||
button,
|
button,
|
||||||
pressed,
|
pressed,
|
||||||
Modifiers::from_button(e),
|
modifiers,
|
||||||
MouseFormat::from_mode(mode),
|
MouseFormat::from_mode(mode),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -168,19 +137,19 @@ pub fn mouse_button_report(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_moved_report(point: Point, e: &MouseMovedEvent, mode: TermMode) -> Option<Vec<u8>> {
|
pub fn mouse_moved_report(point: AlacPoint, e: &MouseMoveEvent, mode: TermMode) -> Option<Vec<u8>> {
|
||||||
let button = MouseButton::from_move(e);
|
let button = AlacMouseButton::from_move(e);
|
||||||
|
|
||||||
if !button.is_other() && mode.intersects(TermMode::MOUSE_MOTION | TermMode::MOUSE_DRAG) {
|
if !button.is_other() && mode.intersects(TermMode::MOUSE_MOTION | TermMode::MOUSE_DRAG) {
|
||||||
//Only drags are reported in drag mode, so block NoneMove.
|
//Only drags are reported in drag mode, so block NoneMove.
|
||||||
if mode.contains(TermMode::MOUSE_DRAG) && matches!(button, MouseButton::NoneMove) {
|
if mode.contains(TermMode::MOUSE_DRAG) && matches!(button, AlacMouseButton::NoneMove) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
mouse_report(
|
mouse_report(
|
||||||
point,
|
point,
|
||||||
button,
|
button,
|
||||||
true,
|
true,
|
||||||
Modifiers::from_moved(e),
|
e.modifiers,
|
||||||
MouseFormat::from_mode(mode),
|
MouseFormat::from_mode(mode),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -189,19 +158,26 @@ pub fn mouse_moved_report(point: Point, e: &MouseMovedEvent, mode: TermMode) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_side(pos: Vector2F, cur_size: TerminalSize) -> alacritty_terminal::index::Direction {
|
pub fn mouse_side(
|
||||||
if cur_size.cell_width as usize == 0 {
|
pos: Point<Pixels>,
|
||||||
|
cur_size: TerminalSize,
|
||||||
|
) -> alacritty_terminal::index::Direction {
|
||||||
|
let cell_width = cur_size.cell_width.floor();
|
||||||
|
if cell_width == px(0.) {
|
||||||
return Side::Right;
|
return Side::Right;
|
||||||
}
|
}
|
||||||
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 x = pos.x.floor();
|
||||||
let half_cell_width = (cur_size.cell_width / 2.0) as usize;
|
|
||||||
|
let cell_x = cmp::max(px(0.), x - cell_width) % cell_width;
|
||||||
|
let half_cell_width = (cur_size.cell_width / 2.0).floor();
|
||||||
let additional_padding = (cur_size.width() - cur_size.cell_width * 2.) % cur_size.cell_width;
|
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;
|
let end_of_grid = cur_size.width() - cur_size.cell_width - additional_padding;
|
||||||
|
|
||||||
//Width: Pixels or columns?
|
//Width: Pixels or columns?
|
||||||
if cell_x > half_cell_width
|
if cell_x > half_cell_width
|
||||||
// Edge case when mouse leaves the window.
|
// Edge case when mouse leaves the window.
|
||||||
|| x as f32 >= end_of_grid
|
|| x >= end_of_grid
|
||||||
{
|
{
|
||||||
Side::Right
|
Side::Right
|
||||||
} else {
|
} else {
|
||||||
|
@ -209,18 +185,18 @@ pub fn mouse_side(pos: Vector2F, cur_size: TerminalSize) -> alacritty_terminal::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grid_point(pos: Vector2F, cur_size: TerminalSize, display_offset: usize) -> Point {
|
pub fn grid_point(pos: Point<Pixels>, cur_size: TerminalSize, display_offset: usize) -> AlacPoint {
|
||||||
let col = pos.x() / cur_size.cell_width;
|
let col = GridCol((pos.x / cur_size.cell_width).as_usize());
|
||||||
let col = min(GridCol(col as usize), cur_size.last_column());
|
let col = min(col, cur_size.last_column());
|
||||||
let line = pos.y() / cur_size.line_height;
|
let line = (pos.y / cur_size.line_height).as_isize() as i32;
|
||||||
let line = min(line as i32, cur_size.bottommost_line().0);
|
let line = min(line, cur_size.bottommost_line().0);
|
||||||
Point::new(GridLine(line - display_offset as i32), col)
|
AlacPoint::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
|
///Generate the bytes to send to the terminal, from the cell location, a mouse event, and the terminal mode
|
||||||
fn mouse_report(
|
fn mouse_report(
|
||||||
point: Point,
|
point: AlacPoint,
|
||||||
button: MouseButton,
|
button: AlacMouseButton,
|
||||||
pressed: bool,
|
pressed: bool,
|
||||||
modifiers: Modifiers,
|
modifiers: Modifiers,
|
||||||
format: MouseFormat,
|
format: MouseFormat,
|
||||||
|
@ -236,7 +212,7 @@ fn mouse_report(
|
||||||
if modifiers.alt {
|
if modifiers.alt {
|
||||||
mods += 8;
|
mods += 8;
|
||||||
}
|
}
|
||||||
if modifiers.ctrl {
|
if modifiers.control {
|
||||||
mods += 16;
|
mods += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +230,8 @@ fn mouse_report(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normal_mouse_report(point: Point, button: u8, utf8: bool) -> Option<Vec<u8>> {
|
fn normal_mouse_report(point: AlacPoint, button: u8, utf8: bool) -> Option<Vec<u8>> {
|
||||||
let Point { line, column } = point;
|
let AlacPoint { line, column } = point;
|
||||||
let max_point = if utf8 { 2015 } else { 223 };
|
let max_point = if utf8 { 2015 } else { 223 };
|
||||||
|
|
||||||
if line >= max_point || column >= max_point {
|
if line >= max_point || column >= max_point {
|
||||||
|
@ -286,7 +262,7 @@ fn normal_mouse_report(point: Point, button: u8, utf8: bool) -> Option<Vec<u8>>
|
||||||
Some(msg)
|
Some(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sgr_mouse_report(point: Point, button: u8, pressed: bool) -> String {
|
fn sgr_mouse_report(point: AlacPoint, button: u8, pressed: bool) -> String {
|
||||||
let c = if pressed { 'M' } else { 'm' };
|
let c = if pressed { 'M' } else { 'm' };
|
||||||
|
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
|
@ -299,38 +275,3 @@ fn sgr_mouse_report(point: Point, button: u8, pressed: bool) -> String {
|
||||||
|
|
||||||
msg
|
msg
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use crate::mappings::mouse::grid_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 = grid_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),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ use terminal_settings::{AlternateScroll, Shell, TerminalBlink, TerminalSettings}
|
||||||
use util::truncate_and_trailoff;
|
use util::truncate_and_trailoff;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp::min,
|
cmp::{self, min},
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
ops::{Deref, Index, RangeInclusive},
|
ops::{Deref, Index, RangeInclusive},
|
||||||
|
@ -49,15 +49,12 @@ use std::{
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use gpui2::{
|
use gpui2::{
|
||||||
px, AnyWindowHandle, AppContext, ClipboardItem, EventEmitter, Keystroke, MainThread,
|
px, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, Hsla, Keystroke,
|
||||||
ModelContext, Modifiers, MouseButton, MouseDragEvent, MouseScrollWheel, MouseUp, Pixels, Point,
|
MainThread, ModelContext, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||||
Task, TouchPhase,
|
Pixels, Point, ScrollWheelEvent, Size, Task, TouchPhase,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::mappings::{
|
use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str};
|
||||||
colors::{get_color_at_index, to_alac_rgb},
|
|
||||||
keys::to_esc_str,
|
|
||||||
};
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
||||||
|
@ -136,34 +133,32 @@ pub fn init(cx: &mut AppContext) {
|
||||||
pub struct TerminalSize {
|
pub struct TerminalSize {
|
||||||
pub cell_width: Pixels,
|
pub cell_width: Pixels,
|
||||||
pub line_height: Pixels,
|
pub line_height: Pixels,
|
||||||
pub height: Pixels,
|
pub size: Size<Pixels>,
|
||||||
pub width: Pixels,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalSize {
|
impl TerminalSize {
|
||||||
pub fn new(line_height: Pixels, cell_width: Pixels, size: Point<Pixels>) -> Self {
|
pub fn new(line_height: Pixels, cell_width: Pixels, size: Size<Pixels>) -> Self {
|
||||||
TerminalSize {
|
TerminalSize {
|
||||||
cell_width,
|
cell_width,
|
||||||
line_height,
|
line_height,
|
||||||
width: size.x(),
|
size,
|
||||||
height: size.y(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_lines(&self) -> usize {
|
pub fn num_lines(&self) -> usize {
|
||||||
(self.height / self.line_height).floor() as usize
|
f32::from((self.size.height / self.line_height).floor()) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_columns(&self) -> usize {
|
pub fn num_columns(&self) -> usize {
|
||||||
(self.width / self.cell_width).floor() as usize
|
f32::from((self.size.width / self.cell_width).floor()) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height(&self) -> Pixels {
|
pub fn height(&self) -> Pixels {
|
||||||
self.height
|
self.size.height
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&self) -> Pixels {
|
pub fn width(&self) -> Pixels {
|
||||||
self.width
|
self.size.width
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cell_width(&self) -> Pixels {
|
pub fn cell_width(&self) -> Pixels {
|
||||||
|
@ -179,7 +174,10 @@ impl Default for TerminalSize {
|
||||||
TerminalSize::new(
|
TerminalSize::new(
|
||||||
DEBUG_LINE_HEIGHT,
|
DEBUG_LINE_HEIGHT,
|
||||||
DEBUG_CELL_WIDTH,
|
DEBUG_CELL_WIDTH,
|
||||||
Point::new(DEBUG_TERMINAL_WIDTH, DEBUG_TERMINAL_HEIGHT),
|
Size {
|
||||||
|
width: DEBUG_TERMINAL_WIDTH,
|
||||||
|
height: DEBUG_TERMINAL_HEIGHT,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,6 +285,7 @@ impl TerminalBuilder {
|
||||||
blink_settings: Option<TerminalBlink>,
|
blink_settings: Option<TerminalBlink>,
|
||||||
alternate_scroll: AlternateScroll,
|
alternate_scroll: AlternateScroll,
|
||||||
window: AnyWindowHandle,
|
window: AnyWindowHandle,
|
||||||
|
color_for_index: impl Fn(usize, &mut AppContext) -> Hsla + Send + Sync + 'static,
|
||||||
) -> Result<TerminalBuilder> {
|
) -> Result<TerminalBuilder> {
|
||||||
let pty_config = {
|
let pty_config = {
|
||||||
let alac_shell = match shell.clone() {
|
let alac_shell = match shell.clone() {
|
||||||
|
@ -392,6 +391,7 @@ impl TerminalBuilder {
|
||||||
selection_phase: SelectionPhase::Ended,
|
selection_phase: SelectionPhase::Ended,
|
||||||
cmd_pressed: false,
|
cmd_pressed: false,
|
||||||
hovered_word: false,
|
hovered_word: false,
|
||||||
|
color_for_index: Box::new(color_for_index),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(TerminalBuilder {
|
Ok(TerminalBuilder {
|
||||||
|
@ -402,7 +402,7 @@ impl TerminalBuilder {
|
||||||
|
|
||||||
pub fn subscribe(mut self, cx: &mut ModelContext<Terminal>) -> Terminal {
|
pub fn subscribe(mut self, cx: &mut ModelContext<Terminal>) -> Terminal {
|
||||||
//Event loop
|
//Event loop
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn_on_main(|this, mut cx| async move {
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
|
||||||
while let Some(event) = self.events_rx.next().await {
|
while let Some(event) = self.events_rx.next().await {
|
||||||
|
@ -545,6 +545,8 @@ pub struct Terminal {
|
||||||
selection_phase: SelectionPhase,
|
selection_phase: SelectionPhase,
|
||||||
cmd_pressed: bool,
|
cmd_pressed: bool,
|
||||||
hovered_word: bool,
|
hovered_word: bool,
|
||||||
|
// An implementation of the 8 bit ANSI color palette
|
||||||
|
color_for_index: Box<dyn Fn(usize, &mut AppContext) -> Hsla + Send + Sync + 'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Terminal {
|
impl Terminal {
|
||||||
|
@ -627,19 +629,17 @@ impl Terminal {
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
InternalEvent::ColorRequest(index, format) => {
|
InternalEvent::ColorRequest(index, format) => {
|
||||||
let color = term.colors()[*index].unwrap_or_else(|| {
|
let color = term.colors()[*index]
|
||||||
let term_style = &theme::current(cx).terminal;
|
.unwrap_or_else(|| to_alac_rgb((self.color_for_index)(*index, cx)));
|
||||||
to_alac_rgb(get_color_at_index(index, &term_style))
|
|
||||||
});
|
|
||||||
self.write_to_pty(format(color))
|
self.write_to_pty(format(color))
|
||||||
}
|
}
|
||||||
InternalEvent::Resize(mut new_size) => {
|
InternalEvent::Resize(mut new_size) => {
|
||||||
new_size.height = f32::max(new_size.line_height, new_size.height);
|
new_size.size.height = cmp::max(new_size.line_height, new_size.height());
|
||||||
new_size.width = f32::max(new_size.cell_width, new_size.width);
|
new_size.size.width = cmp::max(new_size.cell_width, new_size.width());
|
||||||
|
|
||||||
self.last_content.size = new_size.clone();
|
self.last_content.size = new_size.clone();
|
||||||
|
|
||||||
self.pty_tx.0.send(Msg::Resize((new_size).into())).ok();
|
self.pty_tx.0.send(Msg::Resize(new_size.into())).ok();
|
||||||
|
|
||||||
term.resize(new_size);
|
term.resize(new_size);
|
||||||
}
|
}
|
||||||
|
@ -707,7 +707,8 @@ impl Terminal {
|
||||||
|
|
||||||
InternalEvent::Copy => {
|
InternalEvent::Copy => {
|
||||||
if let Some(txt) = term.selection_to_string() {
|
if let Some(txt) = term.selection_to_string() {
|
||||||
cx.write_to_clipboard(ClipboardItem::new(txt))
|
cx.run_on_main(|cx| cx.write_to_clipboard(ClipboardItem::new(txt)))
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InternalEvent::ScrollToAlacPoint(point) => {
|
InternalEvent::ScrollToAlacPoint(point) => {
|
||||||
|
@ -952,11 +953,11 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_modifiers_change(&mut self, modifiers: &Modifiers) -> bool {
|
pub fn try_modifiers_change(&mut self, modifiers: &Modifiers) -> bool {
|
||||||
let changed = self.cmd_pressed != modifiers.cmd;
|
let changed = self.cmd_pressed != modifiers.command;
|
||||||
if !self.cmd_pressed && modifiers.cmd {
|
if !self.cmd_pressed && modifiers.command {
|
||||||
self.refresh_hovered_word();
|
self.refresh_hovered_word();
|
||||||
}
|
}
|
||||||
self.cmd_pressed = modifiers.cmd;
|
self.cmd_pressed = modifiers.command;
|
||||||
changed
|
changed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,14 +984,14 @@ impl Terminal {
|
||||||
let delay = cx.executor().timer(Duration::from_millis(16));
|
let delay = cx.executor().timer(Duration::from_millis(16));
|
||||||
self.sync_task = Some(cx.spawn(|weak_handle, mut cx| async move {
|
self.sync_task = Some(cx.spawn(|weak_handle, mut cx| async move {
|
||||||
delay.await;
|
delay.await;
|
||||||
cx.update(|cx| {
|
if let Some(handle) = weak_handle.upgrade() {
|
||||||
if let Some(handle) = weak_handle.upgrade(cx) {
|
handle
|
||||||
handle.update(cx, |terminal, cx| {
|
.update(&mut cx, |terminal, cx| {
|
||||||
terminal.sync_task.take();
|
terminal.sync_task.take();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
});
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1069,10 +1070,10 @@ impl Terminal {
|
||||||
self.last_content.mode.intersects(TermMode::MOUSE_MODE) && !shift
|
self.last_content.mode.intersects(TermMode::MOUSE_MODE) && !shift
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_move(&mut self, e: &MouseMovedEvent, origin: Point<Pixels>) {
|
pub fn mouse_move(&mut self, e: &MouseMoveEvent, origin: Point<Pixels>) {
|
||||||
let position = e.position.sub(origin);
|
let position = e.position - origin;
|
||||||
self.last_mouse_position = Some(position);
|
self.last_mouse_position = Some(position);
|
||||||
if self.mouse_mode(e.shift) {
|
if self.mouse_mode(e.modifiers.shift) {
|
||||||
let point = grid_point(
|
let point = grid_point(
|
||||||
position,
|
position,
|
||||||
self.last_content.size,
|
self.last_content.size,
|
||||||
|
@ -1099,11 +1100,11 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_drag(&mut self, e: MouseDrag, origin: Point<Pixels>) {
|
pub fn mouse_drag(&mut self, e: MouseMoveEvent, origin: Point<Pixels>) {
|
||||||
let position = e.position.sub(origin);
|
let position = e.position - origin;
|
||||||
self.last_mouse_position = Some(position);
|
self.last_mouse_position = Some(position);
|
||||||
|
|
||||||
if !self.mouse_mode(e.shift) {
|
if !self.mouse_mode(e.modifiers.shift) {
|
||||||
self.selection_phase = SelectionPhase::Selecting;
|
self.selection_phase = SelectionPhase::Selecting;
|
||||||
// Alacritty has the same ordering, of first updating the selection
|
// Alacritty has the same ordering, of first updating the selection
|
||||||
// then scrolling 15ms later
|
// then scrolling 15ms later
|
||||||
|
@ -1125,21 +1126,21 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drag_line_delta(&mut self, e: MouseDrag) -> Option<f32> {
|
fn drag_line_delta(&mut self, e: MouseMoveEvent, region: Bounds<Pixels>) -> Option<f32> {
|
||||||
//TODO: Why do these need to be doubled? Probably the same problem that the IME has
|
//TODO: Why do these need to be doubled? Probably the same problem that the IME has
|
||||||
let top = e.region.origin_y() + (self.last_content.size.line_height * 2.);
|
let top = region.origin.y + (self.last_content.size.line_height * 2.);
|
||||||
let bottom = e.region.lower_left().y() - (self.last_content.size.line_height * 2.);
|
let bottom = region.lower_left().y - (self.last_content.size.line_height * 2.);
|
||||||
let scroll_delta = if e.position.y() < top {
|
let scroll_delta = if e.position.y < top {
|
||||||
(top - e.position.y()).powf(1.1)
|
(top - e.position.y).powf(1.1)
|
||||||
} else if e.position.y() > bottom {
|
} else if e.position.y > bottom {
|
||||||
-((e.position.y() - bottom).powf(1.1))
|
-((e.position.y - bottom).powf(1.1))
|
||||||
} else {
|
} else {
|
||||||
return None; //Nothing to do
|
return None; //Nothing to do
|
||||||
};
|
};
|
||||||
Some(scroll_delta)
|
Some(scroll_delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_down(&mut self, e: &MouseDown, origin: Point<Pixels>) {
|
pub fn mouse_down(&mut self, e: &MouseDownEvent, origin: Point<Pixels>) {
|
||||||
let position = e.position.sub(origin);
|
let position = e.position.sub(origin);
|
||||||
let point = grid_point(
|
let point = grid_point(
|
||||||
position,
|
position,
|
||||||
|
@ -1148,7 +1149,9 @@ impl Terminal {
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.mouse_mode(e.shift) {
|
if self.mouse_mode(e.shift) {
|
||||||
if let Some(bytes) = mouse_button_report(point, e, true, self.last_content.mode) {
|
if let Some(bytes) =
|
||||||
|
mouse_button_report(point, e.button, e.modifiers, true, self.last_content.mode)
|
||||||
|
{
|
||||||
self.pty_tx.notify(bytes);
|
self.pty_tx.notify(bytes);
|
||||||
}
|
}
|
||||||
} else if e.button == MouseButton::Left {
|
} else if e.button == MouseButton::Left {
|
||||||
|
@ -1180,7 +1183,12 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_up(&mut self, e: &MouseUp, origin: Point<Pixels>, cx: &mut ModelContext<Self>) {
|
pub fn mouse_up(
|
||||||
|
&mut self,
|
||||||
|
e: &MouseUpEvent,
|
||||||
|
origin: Point<Pixels>,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) {
|
||||||
let setting = settings2::get::<TerminalSettings>(cx);
|
let setting = settings2::get::<TerminalSettings>(cx);
|
||||||
|
|
||||||
let position = e.position.sub(origin);
|
let position = e.position.sub(origin);
|
||||||
|
@ -1191,7 +1199,9 @@ impl Terminal {
|
||||||
self.last_content.display_offset,
|
self.last_content.display_offset,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(bytes) = mouse_button_report(point, e, false, self.last_content.mode) {
|
if let Some(bytes) =
|
||||||
|
mouse_button_report(point, e.button, e.modifiers, false, self.last_content.mode)
|
||||||
|
{
|
||||||
self.pty_tx.notify(bytes);
|
self.pty_tx.notify(bytes);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1274,7 +1284,7 @@ impl Terminal {
|
||||||
|
|
||||||
// Whenever we hit the edges, reset our stored scroll to 0
|
// Whenever we hit the edges, reset our stored scroll to 0
|
||||||
// so we can respond to changes in direction quickly
|
// so we can respond to changes in direction quickly
|
||||||
self.scroll_px %= self.last_content.size.height;
|
self.scroll_px %= self.last_content.size.height();
|
||||||
|
|
||||||
Some(new_offset - old_offset)
|
Some(new_offset - old_offset)
|
||||||
}
|
}
|
||||||
|
@ -1385,25 +1395,21 @@ fn all_search_matches<'a, T>(
|
||||||
RegexIter::new(start, end, AlacDirection::Right, term, regex)
|
RegexIter::new(start, end, AlacDirection::Right, term, regex)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_index_for_mouse(pos: AlacPoint<Pixels>, size: &TerminalSize) -> usize {
|
fn content_index_for_mouse(pos: Point<Pixels>, size: &TerminalSize) -> usize {
|
||||||
let col = (pos.x() / size.cell_width()).round() as usize;
|
let col = (pos.x / size.cell_width()).round().as_usize();
|
||||||
|
|
||||||
let clamped_col = min(col, size.columns() - 1);
|
let clamped_col = min(col, size.columns() - 1);
|
||||||
|
let row = (pos.y / size.line_height()).round().as_usize();
|
||||||
let row = (pos.y() / size.line_height()).round() as usize;
|
|
||||||
|
|
||||||
let clamped_row = min(row, size.screen_lines() - 1);
|
let clamped_row = min(row, size.screen_lines() - 1);
|
||||||
|
|
||||||
clamped_row * size.columns() + clamped_col
|
clamped_row * size.columns() + clamped_col
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use alacritty_terminal::{
|
use alacritty_terminal::{
|
||||||
index::{AlacColumn, Line},
|
index::{AlacColumn, Line, Point as AlacPoint},
|
||||||
term::cell::Cell,
|
term::cell::Cell,
|
||||||
};
|
};
|
||||||
use gpui2::geometry::vecto::vec2f;
|
use gpui2::{geometry::vecto::vec2f, size, Pixels};
|
||||||
use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng};
|
use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng};
|
||||||
|
|
||||||
use crate::{content_index_for_mouse, IndexedCell, TerminalContent, TerminalSize};
|
use crate::{content_index_for_mouse, IndexedCell, TerminalContent, TerminalSize};
|
||||||
|
@ -1419,10 +1425,12 @@ mod tests {
|
||||||
let cell_size = rng.gen_range(5 * PRECISION..20 * PRECISION) as f32 / PRECISION as f32;
|
let cell_size = rng.gen_range(5 * PRECISION..20 * PRECISION) as f32 / PRECISION as f32;
|
||||||
|
|
||||||
let size = crate::TerminalSize {
|
let size = crate::TerminalSize {
|
||||||
cell_width: cell_size,
|
cell_width: Pixels::from(cell_size),
|
||||||
line_height: cell_size,
|
line_height: Pixels::from(cell_size),
|
||||||
height: cell_size * (viewport_cells as f32),
|
size: size(
|
||||||
width: cell_size * (viewport_cells as f32),
|
Pixels::from(cell_size * (viewport_cells as f32)),
|
||||||
|
Pixels::from(cell_size * (viewport_cells as f32)),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let cells = get_cells(size, &mut rng);
|
let cells = get_cells(size, &mut rng);
|
||||||
|
@ -1456,10 +1464,9 @@ mod tests {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
let size = crate::TerminalSize {
|
let size = crate::TerminalSize {
|
||||||
cell_width: 10.,
|
cell_width: Pixels::from(10.),
|
||||||
line_height: 10.,
|
line_height: Pixels::from(10.),
|
||||||
height: 100.,
|
size: size(Pixels::from(100.), Pixels::from(100.)),
|
||||||
width: 100.,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let cells = get_cells(size, &mut rng);
|
let cells = get_cells(size, &mut rng);
|
||||||
|
@ -1478,9 +1485,9 @@ mod tests {
|
||||||
fn get_cells(size: TerminalSize, rng: &mut ThreadRng) -> Vec<Vec<char>> {
|
fn get_cells(size: TerminalSize, rng: &mut ThreadRng) -> Vec<Vec<char>> {
|
||||||
let mut cells = Vec::new();
|
let mut cells = Vec::new();
|
||||||
|
|
||||||
for _ in 0..((size.height() / size.line_height()) as usize) {
|
for _ in 0..(f32::from(size.height() / size.line_height()) as usize) {
|
||||||
let mut row_vec = Vec::new();
|
let mut row_vec = Vec::new();
|
||||||
for _ in 0..((size.width() / size.cell_width()) as usize) {
|
for _ in 0..(f32::from(size.width() / size.cell_width()) as usize) {
|
||||||
let cell_char = rng.sample(Alphanumeric) as char;
|
let cell_char = rng.sample(Alphanumeric) as char;
|
||||||
row_vec.push(cell_char)
|
row_vec.push(cell_char)
|
||||||
}
|
}
|
||||||
|
@ -1497,7 +1504,7 @@ mod tests {
|
||||||
for col in 0..cells[row].len() {
|
for col in 0..cells[row].len() {
|
||||||
let cell_char = cells[row][col];
|
let cell_char = cells[row][col];
|
||||||
ic.push(IndexedCell {
|
ic.push(IndexedCell {
|
||||||
point: Point::new(Line(row as i32), Column(col)),
|
point: AlacPoint::new(Line(row as i32), Column(col)),
|
||||||
cell: Cell {
|
cell: Cell {
|
||||||
c: cell_char,
|
c: cell_char,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use gpui2::{AppContext, FontFeatures};
|
||||||
|
|
||||||
use gpui2::{fonts, AppContext};
|
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
|
@ -19,7 +18,7 @@ pub struct TerminalSettings {
|
||||||
font_size: Option<f32>,
|
font_size: Option<f32>,
|
||||||
pub font_family: Option<String>,
|
pub font_family: Option<String>,
|
||||||
pub line_height: TerminalLineHeight,
|
pub line_height: TerminalLineHeight,
|
||||||
pub font_features: Option<fonts::Features>,
|
pub font_features: Option<FontFeatures>,
|
||||||
pub env: HashMap<String, String>,
|
pub env: HashMap<String, String>,
|
||||||
pub blinking: TerminalBlink,
|
pub blinking: TerminalBlink,
|
||||||
pub alternate_scroll: AlternateScroll,
|
pub alternate_scroll: AlternateScroll,
|
||||||
|
@ -79,7 +78,7 @@ pub struct TerminalSettingsContent {
|
||||||
pub font_size: Option<f32>,
|
pub font_size: Option<f32>,
|
||||||
pub font_family: Option<String>,
|
pub font_family: Option<String>,
|
||||||
pub line_height: Option<TerminalLineHeight>,
|
pub line_height: Option<TerminalLineHeight>,
|
||||||
pub font_features: Option<fonts::Features>,
|
pub font_features: Option<FontFeatures>,
|
||||||
pub env: Option<HashMap<String, String>>,
|
pub env: Option<HashMap<String, String>>,
|
||||||
pub blinking: Option<TerminalBlink>,
|
pub blinking: Option<TerminalBlink>,
|
||||||
pub alternate_scroll: Option<AlternateScroll>,
|
pub alternate_scroll: Option<AlternateScroll>,
|
||||||
|
@ -92,10 +91,11 @@ pub struct TerminalSettingsContent {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalSettings {
|
impl TerminalSettings {
|
||||||
pub fn font_size(&self, cx: &AppContext) -> Option<f32> {
|
// todo!("move to terminal element")
|
||||||
self.font_size
|
// pub fn font_size(&self, cx: &AppContext) -> Option<f32> {
|
||||||
.map(|size| theme2::adjusted_font_size(size, cx))
|
// self.font_size
|
||||||
}
|
// .map(|size| theme2::adjusted_font_size(size, cx))
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl settings2::Setting for TerminalSettings {
|
impl settings2::Setting for TerminalSettings {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue