Merge branch 'master' of https://github.com/pop-os/cosmic-term
This commit is contained in:
commit
4cec08875f
8 changed files with 183 additions and 217 deletions
|
|
@ -292,11 +292,11 @@ impl Config {
|
||||||
let color_schemes = self.color_schemes(color_scheme_kind);
|
let color_schemes = self.color_schemes(color_scheme_kind);
|
||||||
let mut color_scheme_names =
|
let mut color_scheme_names =
|
||||||
Vec::<(String, ColorSchemeId)>::with_capacity(color_schemes.len());
|
Vec::<(String, ColorSchemeId)>::with_capacity(color_schemes.len());
|
||||||
for (color_scheme_id, color_scheme) in color_schemes.iter() {
|
for (color_scheme_id, color_scheme) in color_schemes {
|
||||||
let mut name = color_scheme.name.clone();
|
let mut name = color_scheme.name.clone();
|
||||||
|
|
||||||
let mut copies = 1;
|
let mut copies = 1;
|
||||||
while color_scheme_names.iter().find(|x| x.0 == name).is_some() {
|
while color_scheme_names.iter().any(|x| x.0 == name) {
|
||||||
copies += 1;
|
copies += 1;
|
||||||
name = format!("{} ({})", color_scheme.name, copies);
|
name = format!("{} ({})", color_scheme.name, copies);
|
||||||
}
|
}
|
||||||
|
|
@ -322,17 +322,17 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn opacity_ratio(&self) -> f32 {
|
pub fn opacity_ratio(&self) -> f32 {
|
||||||
(self.opacity as f32) / 100.0
|
f32::from(self.opacity) / 100.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a sorted and adjusted for duplicates list of profile names and ids
|
// Get a sorted and adjusted for duplicates list of profile names and ids
|
||||||
pub fn profile_names(&self) -> Vec<(String, ProfileId)> {
|
pub fn profile_names(&self) -> Vec<(String, ProfileId)> {
|
||||||
let mut profile_names = Vec::<(String, ProfileId)>::with_capacity(self.profiles.len());
|
let mut profile_names = Vec::<(String, ProfileId)>::with_capacity(self.profiles.len());
|
||||||
for (profile_id, profile) in self.profiles.iter() {
|
for (profile_id, profile) in &self.profiles {
|
||||||
let mut name = profile.name.clone();
|
let mut name = profile.name.clone();
|
||||||
|
|
||||||
let mut copies = 1;
|
let mut copies = 1;
|
||||||
while profile_names.iter().find(|x| x.0 == name).is_some() {
|
while profile_names.iter().any(|x| x.0 == name) {
|
||||||
copies += 1;
|
copies += 1;
|
||||||
name = format!("{} ({})", profile.name, copies);
|
name = format!("{} ({})", profile.name, copies);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,6 @@ pub fn localize() {
|
||||||
let requested_languages = i18n_embed::DesktopLanguageRequester::requested_languages();
|
let requested_languages = i18n_embed::DesktopLanguageRequester::requested_languages();
|
||||||
|
|
||||||
if let Err(error) = localizer.select(&requested_languages) {
|
if let Err(error) = localizer.select(&requested_languages) {
|
||||||
eprintln!("Error while loading language for App List {}", error);
|
eprintln!("Error while loading language for App List {error}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
267
src/main.rs
267
src/main.rs
|
|
@ -76,7 +76,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Ok(fork::Fork::Child) => (),
|
Ok(fork::Fork::Child) => (),
|
||||||
Ok(fork::Fork::Parent(_child_pid)) => process::exit(0),
|
Ok(fork::Fork::Parent(_child_pid)) => process::exit(0),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("failed to daemonize: {:?}", err);
|
eprintln!("failed to daemonize: {err:?}");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -209,45 +209,45 @@ impl MenuAction for Action {
|
||||||
|
|
||||||
fn message(&self, entity_opt: Option<segmented_button::Entity>) -> Message {
|
fn message(&self, entity_opt: Option<segmented_button::Entity>) -> Message {
|
||||||
match self {
|
match self {
|
||||||
Action::About => Message::ToggleContextPage(ContextPage::About),
|
Self::About => Message::ToggleContextPage(ContextPage::About),
|
||||||
Action::ColorSchemes(color_scheme_kind) => {
|
Self::ColorSchemes(color_scheme_kind) => {
|
||||||
Message::ToggleContextPage(ContextPage::ColorSchemes(*color_scheme_kind))
|
Message::ToggleContextPage(ContextPage::ColorSchemes(*color_scheme_kind))
|
||||||
}
|
}
|
||||||
Action::Copy => Message::Copy(entity_opt),
|
Self::Copy => Message::Copy(entity_opt),
|
||||||
Action::CopyPrimary => Message::CopyPrimary(entity_opt),
|
Self::CopyPrimary => Message::CopyPrimary(entity_opt),
|
||||||
Action::Find => Message::Find(true),
|
Self::Find => Message::Find(true),
|
||||||
Action::PaneFocusDown => Message::PaneFocusAdjacent(pane_grid::Direction::Down),
|
Self::PaneFocusDown => Message::PaneFocusAdjacent(pane_grid::Direction::Down),
|
||||||
Action::PaneFocusLeft => Message::PaneFocusAdjacent(pane_grid::Direction::Left),
|
Self::PaneFocusLeft => Message::PaneFocusAdjacent(pane_grid::Direction::Left),
|
||||||
Action::PaneFocusRight => Message::PaneFocusAdjacent(pane_grid::Direction::Right),
|
Self::PaneFocusRight => Message::PaneFocusAdjacent(pane_grid::Direction::Right),
|
||||||
Action::PaneFocusUp => Message::PaneFocusAdjacent(pane_grid::Direction::Up),
|
Self::PaneFocusUp => Message::PaneFocusAdjacent(pane_grid::Direction::Up),
|
||||||
Action::PaneSplitHorizontal => Message::PaneSplit(pane_grid::Axis::Horizontal),
|
Self::PaneSplitHorizontal => Message::PaneSplit(pane_grid::Axis::Horizontal),
|
||||||
Action::PaneSplitVertical => Message::PaneSplit(pane_grid::Axis::Vertical),
|
Self::PaneSplitVertical => Message::PaneSplit(pane_grid::Axis::Vertical),
|
||||||
Action::PaneToggleMaximized => Message::PaneToggleMaximized,
|
Self::PaneToggleMaximized => Message::PaneToggleMaximized,
|
||||||
Action::Paste => Message::Paste(entity_opt),
|
Self::Paste => Message::Paste(entity_opt),
|
||||||
Action::PastePrimary => Message::PastePrimary(entity_opt),
|
Self::PastePrimary => Message::PastePrimary(entity_opt),
|
||||||
Action::ProfileOpen(profile_id) => Message::ProfileOpen(*profile_id),
|
Self::ProfileOpen(profile_id) => Message::ProfileOpen(*profile_id),
|
||||||
Action::Profiles => Message::ToggleContextPage(ContextPage::Profiles),
|
Self::Profiles => Message::ToggleContextPage(ContextPage::Profiles),
|
||||||
Action::SelectAll => Message::SelectAll(entity_opt),
|
Self::SelectAll => Message::SelectAll(entity_opt),
|
||||||
Action::Settings => Message::ToggleContextPage(ContextPage::Settings),
|
Self::Settings => Message::ToggleContextPage(ContextPage::Settings),
|
||||||
Action::ShowHeaderBar(show_headerbar) => Message::ShowHeaderBar(*show_headerbar),
|
Self::ShowHeaderBar(show_headerbar) => Message::ShowHeaderBar(*show_headerbar),
|
||||||
Action::TabActivate0 => Message::TabActivateJump(0),
|
Self::TabActivate0 => Message::TabActivateJump(0),
|
||||||
Action::TabActivate1 => Message::TabActivateJump(1),
|
Self::TabActivate1 => Message::TabActivateJump(1),
|
||||||
Action::TabActivate2 => Message::TabActivateJump(2),
|
Self::TabActivate2 => Message::TabActivateJump(2),
|
||||||
Action::TabActivate3 => Message::TabActivateJump(3),
|
Self::TabActivate3 => Message::TabActivateJump(3),
|
||||||
Action::TabActivate4 => Message::TabActivateJump(4),
|
Self::TabActivate4 => Message::TabActivateJump(4),
|
||||||
Action::TabActivate5 => Message::TabActivateJump(5),
|
Self::TabActivate5 => Message::TabActivateJump(5),
|
||||||
Action::TabActivate6 => Message::TabActivateJump(6),
|
Self::TabActivate6 => Message::TabActivateJump(6),
|
||||||
Action::TabActivate7 => Message::TabActivateJump(7),
|
Self::TabActivate7 => Message::TabActivateJump(7),
|
||||||
Action::TabActivate8 => Message::TabActivateJump(8),
|
Self::TabActivate8 => Message::TabActivateJump(8),
|
||||||
Action::TabClose => Message::TabClose(entity_opt),
|
Self::TabClose => Message::TabClose(entity_opt),
|
||||||
Action::TabNew => Message::TabNew,
|
Self::TabNew => Message::TabNew,
|
||||||
Action::TabNext => Message::TabNext,
|
Self::TabNext => Message::TabNext,
|
||||||
Action::TabPrev => Message::TabPrev,
|
Self::TabPrev => Message::TabPrev,
|
||||||
Action::WindowClose => Message::WindowClose,
|
Self::WindowClose => Message::WindowClose,
|
||||||
Action::WindowNew => Message::WindowNew,
|
Self::WindowNew => Message::WindowNew,
|
||||||
Action::ZoomIn => Message::ZoomIn,
|
Self::ZoomIn => Message::ZoomIn,
|
||||||
Action::ZoomOut => Message::ZoomOut,
|
Self::ZoomOut => Message::ZoomOut,
|
||||||
Action::ZoomReset => Message::ZoomReset,
|
Self::ZoomReset => Message::ZoomReset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -460,9 +460,9 @@ impl App {
|
||||||
{
|
{
|
||||||
let color = Color::from(theme.cosmic().background.base);
|
let color = Color::from(theme.cosmic().background.base);
|
||||||
let bytes = color.into_rgba8();
|
let bytes = color.into_rgba8();
|
||||||
let data = (bytes[2] as u32)
|
let data = u32::from(bytes[2])
|
||||||
| ((bytes[1] as u32) << 8)
|
| (u32::from(bytes[1]) << 8)
|
||||||
| ((bytes[0] as u32) << 16)
|
| (u32::from(bytes[0]) << 16)
|
||||||
| 0xFF000000;
|
| 0xFF000000;
|
||||||
terminal::WINDOW_BG_COLOR.store(data, Ordering::SeqCst);
|
terminal::WINDOW_BG_COLOR.store(data, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
@ -499,17 +499,14 @@ impl App {
|
||||||
fn save_color_schemes(&mut self, color_scheme_kind: ColorSchemeKind) -> Command<Message> {
|
fn save_color_schemes(&mut self, color_scheme_kind: ColorSchemeKind) -> Command<Message> {
|
||||||
// Optimized for just saving color_schemes
|
// Optimized for just saving color_schemes
|
||||||
if let Some(ref config_handler) = self.config_handler {
|
if let Some(ref config_handler) = self.config_handler {
|
||||||
match config_handler.set(
|
if let Err(err) = config_handler.set(
|
||||||
match color_scheme_kind {
|
match color_scheme_kind {
|
||||||
ColorSchemeKind::Dark => "color_schemes_dark",
|
ColorSchemeKind::Dark => "color_schemes_dark",
|
||||||
ColorSchemeKind::Light => "color_schemes_light",
|
ColorSchemeKind::Light => "color_schemes_light",
|
||||||
},
|
},
|
||||||
&self.config.color_schemes(color_scheme_kind),
|
self.config.color_schemes(color_scheme_kind),
|
||||||
) {
|
) {
|
||||||
Ok(()) => {}
|
log::error!("failed to save config: {}", err);
|
||||||
Err(err) => {
|
|
||||||
log::error!("failed to save config: {}", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_color_schemes();
|
self.update_color_schemes();
|
||||||
|
|
@ -664,7 +661,7 @@ impl App {
|
||||||
hash = short_hash.as_str(),
|
hash = short_hash.as_str(),
|
||||||
date = date
|
date = date
|
||||||
))
|
))
|
||||||
.on_press(Message::LaunchUrl(format!("{}/commits/{}", repository, hash)))
|
.on_press(Message::LaunchUrl(format!("{repository}/commits/{hash}")))
|
||||||
.padding(0)
|
.padding(0)
|
||||||
.into(),
|
.into(),
|
||||||
])
|
])
|
||||||
|
|
@ -754,7 +751,7 @@ impl App {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
for error in self.color_scheme_errors.iter() {
|
for error in &self.color_scheme_errors {
|
||||||
sections.push(
|
sections.push(
|
||||||
widget::row::with_children(vec } {
|
if let Err(err) =
|
||||||
Ok(_) => {}
|
paste::paste! { self.config.[<set_ $name>](config_handler, $value) }
|
||||||
Err(err) => {
|
{
|
||||||
log::warn!(
|
log::warn!("failed to save config {:?}: {}", stringify!($name), err);
|
||||||
"failed to save config {:?}: {}",
|
|
||||||
stringify!($name),
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -1532,7 +1522,7 @@ impl Application for App {
|
||||||
move |result| {
|
move |result| {
|
||||||
Message::ColorSchemeExportResult(
|
Message::ColorSchemeExportResult(
|
||||||
color_scheme_kind,
|
color_scheme_kind,
|
||||||
color_scheme_id.clone(),
|
color_scheme_id,
|
||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -1556,9 +1546,8 @@ impl Application for App {
|
||||||
&color_scheme,
|
&color_scheme,
|
||||||
ron::ser::PrettyConfig::new(),
|
ron::ser::PrettyConfig::new(),
|
||||||
) {
|
) {
|
||||||
Ok(ron) => match fs::write(path, &ron) {
|
Ok(ron) => {
|
||||||
Ok(()) => {}
|
if let Err(err) = fs::write(path, ron) {
|
||||||
Err(err) => {
|
|
||||||
log::error!(
|
log::error!(
|
||||||
"failed to export {:?} to {:?}: {}",
|
"failed to export {:?} to {:?}: {}",
|
||||||
color_scheme_id,
|
color_scheme_id,
|
||||||
|
|
@ -1566,7 +1555,7 @@ impl Application for App {
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
"failed to serialize color scheme {:?}: {}",
|
"failed to serialize color scheme {:?}: {}",
|
||||||
|
|
@ -1600,12 +1589,12 @@ impl Application for App {
|
||||||
self.dialog_opt = None;
|
self.dialog_opt = None;
|
||||||
if let DialogResult::Open(paths) = result {
|
if let DialogResult::Open(paths) = result {
|
||||||
self.color_scheme_errors.clear();
|
self.color_scheme_errors.clear();
|
||||||
for path in paths.iter() {
|
for path in &paths {
|
||||||
let mut file = match fs::File::open(path) {
|
let mut file = match fs::File::open(path) {
|
||||||
Ok(ok) => ok,
|
Ok(ok) => ok,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.color_scheme_errors
|
self.color_scheme_errors
|
||||||
.push(format!("Failed to open {:?}: {}", path, err));
|
.push(format!("Failed to open {path:?}: {err}"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1624,7 +1613,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.color_scheme_errors
|
self.color_scheme_errors
|
||||||
.push(format!("Failed to parse {:?}: {}", path, err));
|
.push(format!("Failed to parse {path:?}: {err}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1866,18 +1855,17 @@ impl Application for App {
|
||||||
config_set!(focus_follow_mouse, focus_follow_mouse);
|
config_set!(focus_follow_mouse, focus_follow_mouse);
|
||||||
}
|
}
|
||||||
Message::Key(modifiers, key) => {
|
Message::Key(modifiers, key) => {
|
||||||
for (key_bind, action) in self.key_binds.iter() {
|
for (key_bind, action) in &self.key_binds {
|
||||||
if key_bind.matches(modifiers, &key) {
|
if key_bind.matches(modifiers, &key) {
|
||||||
return self.update(action.message(None));
|
return self.update(action.message(None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::LaunchUrl(url) => match open::that_detached(&url) {
|
Message::LaunchUrl(url) => {
|
||||||
Ok(()) => {}
|
if let Err(err) = open::that_detached(&url) {
|
||||||
Err(err) => {
|
|
||||||
log::warn!("failed to open {:?}: {}", url, err);
|
log::warn!("failed to open {:?}: {}", url, err);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Message::Modifiers(modifiers) => {
|
Message::Modifiers(modifiers) => {
|
||||||
self.modifiers = modifiers;
|
self.modifiers = modifiers;
|
||||||
}
|
}
|
||||||
|
|
@ -2367,31 +2355,28 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extra work to do to prepare context pages
|
// Extra work to do to prepare context pages
|
||||||
match self.context_page {
|
if let ContextPage::ColorSchemes(color_scheme_kind) = self.context_page {
|
||||||
ContextPage::ColorSchemes(color_scheme_kind) => {
|
self.color_scheme_errors.clear();
|
||||||
self.color_scheme_errors.clear();
|
self.color_scheme_expanded = None;
|
||||||
self.color_scheme_expanded = None;
|
self.color_scheme_renaming = None;
|
||||||
self.color_scheme_renaming = None;
|
self.color_scheme_tab_model = widget::segmented_button::Model::default();
|
||||||
self.color_scheme_tab_model = widget::segmented_button::Model::default();
|
let dark_entity = self
|
||||||
let dark_entity = self
|
.color_scheme_tab_model
|
||||||
.color_scheme_tab_model
|
.insert()
|
||||||
.insert()
|
.text(fl!("dark"))
|
||||||
.text(fl!("dark"))
|
.data(ColorSchemeKind::Dark)
|
||||||
.data(ColorSchemeKind::Dark)
|
.id();
|
||||||
.id();
|
let light_entity = self
|
||||||
let light_entity = self
|
.color_scheme_tab_model
|
||||||
.color_scheme_tab_model
|
.insert()
|
||||||
.insert()
|
.text(fl!("light"))
|
||||||
.text(fl!("light"))
|
.data(ColorSchemeKind::Light)
|
||||||
.data(ColorSchemeKind::Light)
|
.id();
|
||||||
.id();
|
self.color_scheme_tab_model
|
||||||
self.color_scheme_tab_model
|
.activate(match color_scheme_kind {
|
||||||
.activate(match color_scheme_kind {
|
ColorSchemeKind::Dark => dark_entity,
|
||||||
ColorSchemeKind::Dark => dark_entity,
|
ColorSchemeKind::Light => light_entity,
|
||||||
ColorSchemeKind::Light => light_entity,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_context_title(context_page.title());
|
self.set_context_title(context_page.title());
|
||||||
|
|
@ -2491,41 +2476,33 @@ impl Application for App {
|
||||||
.get(&pane)
|
.get(&pane)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(widget::Id::unique);
|
.unwrap_or_else(widget::Id::unique);
|
||||||
match tab_model.data::<Mutex<Terminal>>(entity) {
|
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
|
||||||
Some(terminal) => {
|
let mut terminal_box = terminal_box(terminal)
|
||||||
let mut terminal_box = terminal_box(terminal)
|
.id(terminal_id)
|
||||||
.id(terminal_id)
|
.on_context_menu(move |position_opt| {
|
||||||
.on_context_menu(move |position_opt| {
|
Message::TabContextMenu(pane, position_opt)
|
||||||
Message::TabContextMenu(pane, position_opt)
|
})
|
||||||
})
|
.on_middle_click(move || Message::MiddleClick(pane, Some(entity_middle_click)))
|
||||||
.on_middle_click(move || {
|
.opacity(self.config.opacity_ratio())
|
||||||
Message::MiddleClick(pane, Some(entity_middle_click))
|
.padding(space_xxs);
|
||||||
})
|
|
||||||
.opacity(self.config.opacity_ratio())
|
|
||||||
.padding(space_xxs);
|
|
||||||
|
|
||||||
if self.config.focus_follow_mouse {
|
if self.config.focus_follow_mouse {
|
||||||
terminal_box =
|
terminal_box = terminal_box.on_mouse_enter(move || Message::MouseEnter(pane));
|
||||||
terminal_box.on_mouse_enter(move || Message::MouseEnter(pane));
|
|
||||||
}
|
|
||||||
|
|
||||||
let context_menu = {
|
|
||||||
let terminal = terminal.lock().unwrap();
|
|
||||||
terminal.context_menu
|
|
||||||
};
|
|
||||||
|
|
||||||
let tab_element: Element<'_, Message> = match context_menu {
|
|
||||||
Some(point) => widget::popover(terminal_box.context_menu(point))
|
|
||||||
.popup(menu::context_menu(&self.config, &self.key_binds, entity))
|
|
||||||
.position(widget::popover::Position::Point(point))
|
|
||||||
.into(),
|
|
||||||
None => terminal_box.into(),
|
|
||||||
};
|
|
||||||
tab_column = tab_column.push(tab_element);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
//TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let context_menu = {
|
||||||
|
let terminal = terminal.lock().unwrap();
|
||||||
|
terminal.context_menu
|
||||||
|
};
|
||||||
|
|
||||||
|
let tab_element: Element<'_, Message> = match context_menu {
|
||||||
|
Some(point) => widget::popover(terminal_box.context_menu(point))
|
||||||
|
.popup(menu::context_menu(&self.config, &self.key_binds, entity))
|
||||||
|
.position(widget::popover::Position::Point(point))
|
||||||
|
.into(),
|
||||||
|
None => terminal_box.into(),
|
||||||
|
};
|
||||||
|
tab_column = tab_column.push(tab_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Only draw find in the currently focused pane
|
//Only draw find in the currently focused pane
|
||||||
|
|
@ -2583,6 +2560,8 @@ impl Application for App {
|
||||||
|
|
||||||
tab_column = tab_column
|
tab_column = tab_column
|
||||||
.push(widget::layer_container(find_widget).layer(cosmic_theme::Layer::Primary));
|
.push(widget::layer_container(find_widget).layer(cosmic_theme::Layer::Primary));
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
pane_grid::Content::new(tab_column)
|
pane_grid::Content::new(tab_column)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ pub fn context_menu<'a>(
|
||||||
entity: segmented_button::Entity,
|
entity: segmented_button::Entity,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
let find_key = |action: &Action| -> String {
|
let find_key = |action: &Action| -> String {
|
||||||
for (key_bind, key_action) in key_binds.iter() {
|
for (key_bind, key_action) in key_binds {
|
||||||
if action == key_action {
|
if action == key_action {
|
||||||
return key_bind.to_string();
|
return key_bind.to_string();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ pub struct MouseReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MouseReporter {
|
impl MouseReporter {
|
||||||
fn button_number(&self, button: Button) -> Option<u8> {
|
fn button_number(button: Button) -> Option<u8> {
|
||||||
match button {
|
match button {
|
||||||
Button::Left => Some(0),
|
Button::Left => Some(0),
|
||||||
Button::Middle => Some(1),
|
Button::Middle => Some(1),
|
||||||
|
|
@ -36,10 +36,10 @@ impl MouseReporter {
|
||||||
) -> Option<Vec<u8>> {
|
) -> Option<Vec<u8>> {
|
||||||
//Buttons are handle slightly different between normal and sgr
|
//Buttons are handle slightly different between normal and sgr
|
||||||
//for normal/utf8 the button release is always reported as button 3
|
//for normal/utf8 the button release is always reported as button 3
|
||||||
let Some(mut button) = (match event {
|
let mut button = (match event {
|
||||||
Event::Mouse(MouseEvent::ButtonPressed(b)) => {
|
Event::Mouse(MouseEvent::ButtonPressed(b)) => {
|
||||||
self.button = Some(b);
|
self.button = Some(b);
|
||||||
self.button_number(b)
|
Self::button_number(b)
|
||||||
}
|
}
|
||||||
Event::Mouse(MouseEvent::ButtonReleased(_b)) => {
|
Event::Mouse(MouseEvent::ButtonReleased(_b)) => {
|
||||||
self.button = None;
|
self.button = None;
|
||||||
|
|
@ -59,14 +59,10 @@ impl MouseReporter {
|
||||||
//character, Cb).
|
//character, Cb).
|
||||||
//For example, motion into cell x,y with button 1 down is reported as
|
//For example, motion into cell x,y with button 1 down is reported as
|
||||||
//CSI M @ CxCy ( @ = 32 + 0 (button 1) + 32 (motion indicator) ).
|
//CSI M @ CxCy ( @ = 32 + 0 (button 1) + 32 (motion indicator) ).
|
||||||
self.button
|
self.button.and_then(Self::button_number).map(|b| b + 32)
|
||||||
.and_then(|button| self.button_number(button))
|
|
||||||
.map(|b| b + 32)
|
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}) else {
|
})?;
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
if modifiers.shift() {
|
if modifiers.shift() {
|
||||||
button += 4;
|
button += 4;
|
||||||
|
|
@ -127,16 +123,16 @@ impl MouseReporter {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
) -> Option<Vec<u8>> {
|
) -> Option<Vec<u8>> {
|
||||||
let Some((button_no, event_code)) = (match event {
|
let (button_no, event_code) = (match event {
|
||||||
Event::Mouse(MouseEvent::ButtonPressed(button)) => {
|
Event::Mouse(MouseEvent::ButtonPressed(button)) => {
|
||||||
//Button pressed is reported as button 0,1,2 and event code M
|
//Button pressed is reported as button 0,1,2 and event code M
|
||||||
self.button = Some(button);
|
self.button = Some(button);
|
||||||
Some((self.button_number(button), "M"))
|
Some((Self::button_number(button), "M"))
|
||||||
}
|
}
|
||||||
Event::Mouse(MouseEvent::ButtonReleased(button)) => {
|
Event::Mouse(MouseEvent::ButtonReleased(button)) => {
|
||||||
//Button pressed is reported as button 0,1,2 and event code m
|
//Button pressed is reported as button 0,1,2 and event code m
|
||||||
self.button = None;
|
self.button = None;
|
||||||
Some((self.button_number(button), "m"))
|
Some((Self::button_number(button), "m"))
|
||||||
}
|
}
|
||||||
Event::Mouse(MouseEvent::CursorMoved { .. }) => {
|
Event::Mouse(MouseEvent::CursorMoved { .. }) => {
|
||||||
//Button pressed is reported as button 32 + 0,1,2 and event code M
|
//Button pressed is reported as button 32 + 0,1,2 and event code M
|
||||||
|
|
@ -148,12 +144,10 @@ impl MouseReporter {
|
||||||
self.last_movment_y = Some(y);
|
self.last_movment_y = Some(y);
|
||||||
}
|
}
|
||||||
self.button
|
self.button
|
||||||
.map(|button| (self.button_number(button).map(|b| b + 32), "M"))
|
.map(|button| (Self::button_number(button).map(|b| b + 32), "M"))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}) else {
|
})?;
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(mut button_no) = button_no {
|
if let Some(mut button_no) = button_no {
|
||||||
if modifiers.shift() {
|
if modifiers.shift() {
|
||||||
|
|
@ -174,7 +168,6 @@ impl MouseReporter {
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn report_sgr_mouse_wheel_scroll(
|
pub fn report_sgr_mouse_wheel_scroll(
|
||||||
&self,
|
|
||||||
terminal: &Terminal,
|
terminal: &Terminal,
|
||||||
term_cell_width: f32,
|
term_cell_width: f32,
|
||||||
term_cell_height: f32,
|
term_cell_height: f32,
|
||||||
|
|
@ -217,7 +210,6 @@ impl MouseReporter {
|
||||||
//Emulate mouse wheel scroll with up/down arrows. Using mouse spec uses
|
//Emulate mouse wheel scroll with up/down arrows. Using mouse spec uses
|
||||||
//scroll-back and scroll-forw actions, which moves whole windows like page up/page down.
|
//scroll-back and scroll-forw actions, which moves whole windows like page up/page down.
|
||||||
pub fn report_mouse_wheel_as_arrows(
|
pub fn report_mouse_wheel_as_arrows(
|
||||||
&self,
|
|
||||||
terminal: &Terminal,
|
terminal: &Terminal,
|
||||||
term_cell_width: f32,
|
term_cell_width: f32,
|
||||||
term_cell_height: f32,
|
term_cell_height: f32,
|
||||||
|
|
|
||||||
|
|
@ -110,25 +110,25 @@ fn convert_color(colors: &Colors, color: Color) -> cosmic_text::Color {
|
||||||
let rgb = match color {
|
let rgb = match color {
|
||||||
Color::Named(named_color) => match colors[named_color] {
|
Color::Named(named_color) => match colors[named_color] {
|
||||||
Some(rgb) => rgb,
|
Some(rgb) => rgb,
|
||||||
None => match named_color {
|
None => {
|
||||||
NamedColor::Background => {
|
if named_color == NamedColor::Background {
|
||||||
// Allow using an unset background
|
// Allow using an unset background
|
||||||
return cosmic_text::Color(WINDOW_BG_COLOR.load(Ordering::SeqCst));
|
return cosmic_text::Color(WINDOW_BG_COLOR.load(Ordering::SeqCst));
|
||||||
}
|
} else {
|
||||||
_ => {
|
|
||||||
log::warn!("missing named color {:?}", named_color);
|
log::warn!("missing named color {:?}", named_color);
|
||||||
Rgb::default()
|
Rgb::default()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
Color::Spec(rgb) => rgb,
|
Color::Spec(rgb) => rgb,
|
||||||
Color::Indexed(index) => match colors[index as usize] {
|
Color::Indexed(index) => {
|
||||||
Some(rgb) => rgb,
|
if let Some(rgb) = colors[index as usize] {
|
||||||
None => {
|
rgb
|
||||||
|
} else {
|
||||||
log::warn!("missing indexed color {}", index);
|
log::warn!("missing indexed color {}", index);
|
||||||
Rgb::default()
|
Rgb::default()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
cosmic_text::Color::rgb(rgb.r, rgb.g, rgb.b)
|
cosmic_text::Color::rgb(rgb.r, rgb.g, rgb.b)
|
||||||
}
|
}
|
||||||
|
|
@ -437,9 +437,8 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let search_regex = match &mut self.search_regex_opt {
|
let Some(search_regex) = &mut self.search_regex_opt else {
|
||||||
Some(some) => some,
|
return;
|
||||||
None => return,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determine search origin
|
// Determine search origin
|
||||||
|
|
@ -856,7 +855,7 @@ impl Terminal {
|
||||||
let term_lock = self.term.lock();
|
let term_lock = self.term.lock();
|
||||||
let mode = term_lock.mode();
|
let mode = term_lock.mode();
|
||||||
if mode.contains(TermMode::SGR_MOUSE) {
|
if mode.contains(TermMode::SGR_MOUSE) {
|
||||||
self.mouse_reporter.report_sgr_mouse_wheel_scroll(
|
MouseReporter::report_sgr_mouse_wheel_scroll(
|
||||||
self,
|
self,
|
||||||
self.size().cell_width,
|
self.size().cell_width,
|
||||||
self.size().cell_height,
|
self.size().cell_height,
|
||||||
|
|
@ -866,7 +865,7 @@ impl Terminal {
|
||||||
y,
|
y,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.mouse_reporter.report_mouse_wheel_as_arrows(
|
MouseReporter::report_mouse_wheel_as_arrows(
|
||||||
self,
|
self,
|
||||||
self.size().cell_width,
|
self.size().cell_width,
|
||||||
self.size().cell_height,
|
self.size().cell_height,
|
||||||
|
|
|
||||||
|
|
@ -172,10 +172,9 @@ where
|
||||||
// Calculate layout lines
|
// Calculate layout lines
|
||||||
terminal.with_buffer(|buffer| {
|
terminal.with_buffer(|buffer| {
|
||||||
let mut layout_lines = 0;
|
let mut layout_lines = 0;
|
||||||
for line in buffer.lines.iter() {
|
for line in &buffer.lines {
|
||||||
match line.layout_opt() {
|
if let Some(layout) = line.layout_opt() {
|
||||||
Some(layout) => layout_lines += layout.len(),
|
layout_lines += layout.len()
|
||||||
None => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,7 +240,7 @@ where
|
||||||
let state = tree.state.downcast_ref::<State>();
|
let state = tree.state.downcast_ref::<State>();
|
||||||
|
|
||||||
let cosmic_theme = theme.cosmic();
|
let cosmic_theme = theme.cosmic();
|
||||||
let scrollbar_w = cosmic_theme.spacing.space_xxs as f32;
|
let scrollbar_w = f32::from(cosmic_theme.spacing.space_xxs);
|
||||||
|
|
||||||
let view_position = layout.position() + [self.padding.left, self.padding.top].into();
|
let view_position = layout.position() + [self.padding.left, self.padding.top].into();
|
||||||
let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32)
|
let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32)
|
||||||
|
|
@ -278,12 +277,12 @@ where
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Color::new(
|
Color::new(
|
||||||
background_color.r() as f32 / 255.0,
|
f32::from(background_color.r()) / 255.0,
|
||||||
background_color.g() as f32 / 255.0,
|
f32::from(background_color.g()) / 255.0,
|
||||||
background_color.b() as f32 / 255.0,
|
f32::from(background_color.b()) / 255.0,
|
||||||
match self.opacity {
|
match self.opacity {
|
||||||
Some(opacity) => opacity,
|
Some(opacity) => opacity,
|
||||||
None => background_color.a() as f32 / 255.0,
|
None => f32::from(background_color.a()) / 255.0,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -329,10 +328,10 @@ where
|
||||||
) {
|
) {
|
||||||
let cosmic_text_to_iced_color = |color: cosmic_text::Color| {
|
let cosmic_text_to_iced_color = |color: cosmic_text::Color| {
|
||||||
Color::new(
|
Color::new(
|
||||||
color.r() as f32 / 255.0,
|
f32::from(color.r()) / 255.0,
|
||||||
color.g() as f32 / 255.0,
|
f32::from(color.g()) / 255.0,
|
||||||
color.b() as f32 / 255.0,
|
f32::from(color.b()) / 255.0,
|
||||||
color.a() as f32 / 255.0,
|
f32::from(color.a()) / 255.0,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -370,8 +369,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
if !metadata.flags.is_empty() {
|
if !metadata.flags.is_empty() {
|
||||||
let style_line_height =
|
let style_line_height = (self.glyph_font_size / 10.0).clamp(2.0, 16.0);
|
||||||
(self.glyph_font_size / 10.0).max(2.0).min(16.0);
|
|
||||||
|
|
||||||
let line_color = cosmic_text_to_iced_color(metadata.underline_color);
|
let line_color = cosmic_text_to_iced_color(metadata.underline_color);
|
||||||
|
|
||||||
|
|
@ -488,7 +486,7 @@ where
|
||||||
view_position,
|
view_position,
|
||||||
metadata_set,
|
metadata_set,
|
||||||
};
|
};
|
||||||
for glyph in run.glyphs.iter() {
|
for glyph in run.glyphs {
|
||||||
bg_rect.update(glyph, renderer, state.is_focused);
|
bg_rect.update(glyph, renderer, state.is_focused);
|
||||||
}
|
}
|
||||||
bg_rect.fill(renderer, state.is_focused);
|
bg_rect.fill(renderer, state.is_focused);
|
||||||
|
|
@ -606,7 +604,7 @@ where
|
||||||
modifiers,
|
modifiers,
|
||||||
..
|
..
|
||||||
}) if state.is_focused => {
|
}) if state.is_focused => {
|
||||||
for (key_bind, _) in self.key_binds.iter() {
|
for key_bind in self.key_binds.keys() {
|
||||||
if key_bind.matches(modifiers, &Key::Named(named)) {
|
if key_bind.matches(modifiers, &Key::Named(named)) {
|
||||||
return Status::Captured;
|
return Status::Captured;
|
||||||
}
|
}
|
||||||
|
|
@ -705,8 +703,7 @@ where
|
||||||
match named {
|
match named {
|
||||||
Named::Backspace => {
|
Named::Backspace => {
|
||||||
let code = if modifiers.control() { "\x08" } else { "\x7f" };
|
let code = if modifiers.control() { "\x08" } else { "\x7f" };
|
||||||
terminal
|
terminal.input_scroll(format!("{alt_prefix}{code}").as_bytes().to_vec());
|
||||||
.input_scroll(format!("{}{}", alt_prefix, code).as_bytes().to_vec());
|
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
Named::Enter => {
|
Named::Enter => {
|
||||||
|
|
@ -735,8 +732,7 @@ where
|
||||||
}
|
}
|
||||||
Named::Tab => {
|
Named::Tab => {
|
||||||
let code = if modifiers.shift() { "\x1b[Z" } else { "\x09" };
|
let code = if modifiers.shift() { "\x1b[Z" } else { "\x09" };
|
||||||
terminal
|
terminal.input_scroll(format!("{alt_prefix}{code}").as_bytes().to_vec());
|
||||||
.input_scroll(format!("{}{}", alt_prefix, code).as_bytes().to_vec());
|
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
@ -751,7 +747,7 @@ where
|
||||||
key,
|
key,
|
||||||
..
|
..
|
||||||
}) if state.is_focused => {
|
}) if state.is_focused => {
|
||||||
for (key_bind, _) in self.key_binds.iter() {
|
for key_bind in self.key_binds.keys() {
|
||||||
if key_bind.matches(modifiers, &key) {
|
if key_bind.matches(modifiers, &key) {
|
||||||
return Status::Captured;
|
return Status::Captured;
|
||||||
}
|
}
|
||||||
|
|
@ -1064,9 +1060,9 @@ fn shade(color: cosmic_text::Color, is_focused: bool) -> cosmic_text::Color {
|
||||||
} else {
|
} else {
|
||||||
let shade = 0.92;
|
let shade = 0.92;
|
||||||
cosmic_text::Color::rgba(
|
cosmic_text::Color::rgba(
|
||||||
(color.r() as f32 * shade) as u8,
|
(f32::from(color.r()) * shade) as u8,
|
||||||
(color.g() as f32 * shade) as u8,
|
(f32::from(color.g()) * shade) as u8,
|
||||||
(color.b() as f32 * shade) as u8,
|
(f32::from(color.b()) * shade) as u8,
|
||||||
color.a(),
|
color.a(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1106,8 +1102,8 @@ pub struct State {
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
/// Creates a new [`State`].
|
/// Creates a new [`State`].
|
||||||
pub fn new() -> State {
|
pub fn new() -> Self {
|
||||||
State {
|
Self {
|
||||||
modifiers: Modifiers::empty(),
|
modifiers: Modifiers::empty(),
|
||||||
click: None,
|
click: None,
|
||||||
dragging: None,
|
dragging: None,
|
||||||
|
|
@ -1142,7 +1138,7 @@ meta 0b100000 (32)
|
||||||
caps_lock 0b1000000 (64)
|
caps_lock 0b1000000 (64)
|
||||||
num_lock 0b10000000 (128)
|
num_lock 0b10000000 (128)
|
||||||
*/
|
*/
|
||||||
fn calculate_modifier_number(state: &mut State) -> u8 {
|
fn calculate_modifier_number(state: &State) -> u8 {
|
||||||
let mut mod_no = 0;
|
let mut mod_no = 0;
|
||||||
if state.modifiers.shift() {
|
if state.modifiers.shift() {
|
||||||
mod_no |= 1;
|
mod_no |= 1;
|
||||||
|
|
@ -1162,10 +1158,10 @@ fn calculate_modifier_number(state: &mut State) -> u8 {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn csi(code: &str, suffix: &str, modifiers: u8) -> Option<Vec<u8>> {
|
fn csi(code: &str, suffix: &str, modifiers: u8) -> Option<Vec<u8>> {
|
||||||
if modifiers == 1 {
|
if modifiers == 1 {
|
||||||
Some(format!("\x1B[{}{}", code, suffix).as_bytes().to_vec())
|
Some(format!("\x1B[{code}{suffix}").as_bytes().to_vec())
|
||||||
} else {
|
} else {
|
||||||
Some(
|
Some(
|
||||||
format!("\x1B[{};{}{}", code, modifiers, suffix)
|
format!("\x1B[{code};{modifiers}{suffix}")
|
||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec(),
|
.to_vec(),
|
||||||
)
|
)
|
||||||
|
|
@ -1175,8 +1171,8 @@ fn csi(code: &str, suffix: &str, modifiers: u8) -> Option<Vec<u8>> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ss3(code: &str, modifiers: u8) -> Option<Vec<u8>> {
|
fn ss3(code: &str, modifiers: u8) -> Option<Vec<u8>> {
|
||||||
if modifiers == 1 {
|
if modifiers == 1 {
|
||||||
Some(format!("\x1B\x4F{}", code).as_bytes().to_vec())
|
Some(format!("\x1B\x4F{code}").as_bytes().to_vec())
|
||||||
} else {
|
} else {
|
||||||
Some(format!("\x1B[1;{}{}", modifiers, code).as_bytes().to_vec())
|
Some(format!("\x1B[1;{modifiers}{code}").as_bytes().to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ impl ColorDerive {
|
||||||
fn color_adj(rgb: Rgb, saturation_adj: f32, lightness_adj: f32) -> Rgb {
|
fn color_adj(rgb: Rgb, saturation_adj: f32, lightness_adj: f32) -> Rgb {
|
||||||
let mut okhsl = Self::rgb_to_okhsl(rgb);
|
let mut okhsl = Self::rgb_to_okhsl(rgb);
|
||||||
|
|
||||||
okhsl.saturation = (okhsl.saturation + saturation_adj).max(0.0).min(1.0);
|
okhsl.saturation = (okhsl.saturation + saturation_adj).clamp(0.0, 1.0);
|
||||||
okhsl.lightness = (okhsl.lightness + lightness_adj).max(0.0).min(1.0);
|
okhsl.lightness = (okhsl.lightness + lightness_adj).clamp(0.0, 1.0);
|
||||||
|
|
||||||
Self::okhsl_to_rgb(okhsl)
|
Self::okhsl_to_rgb(okhsl)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue