From 204c666f9101b76a6293a8062844e8b0ffc8a756 Mon Sep 17 00:00:00 2001 From: Mattias Eriksson Date: Sat, 20 Jan 2024 14:13:04 +0100 Subject: [PATCH 1/6] Add support for Primary --- src/main.rs | 20 ++++++++++++++++++++ src/terminal_box.rs | 14 +++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index aa3b12f..bbe6a28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -213,6 +213,8 @@ pub enum Message { PaneResized(pane_grid::ResizeEvent), Modifiers(Modifiers), Paste(Option), + #[cfg(target_family = "unix")] + PastePrimary(Option), PasteValue(Option, String), SelectAll(Option), UseBrightBold(bool), @@ -1038,6 +1040,13 @@ impl Application for App { None => message::none(), }); } + #[cfg(target_family = "unix")] + Message::PastePrimary(entity_opt) => { + return clipboard::read_primary(move |value_opt| match value_opt { + Some(value) => message::app(Message::PasteValue(entity_opt, value)), + None => message::none(), + }); + } Message::PasteValue(entity_opt, value) => { if let Some(tab_model) = self.pane_model.active() { let entity = entity_opt.unwrap_or_else(|| tab_model.active()); @@ -1622,6 +1631,17 @@ impl Application for App { None } } + #[cfg(target_family = "unix")] + Event::Keyboard(KeyEvent::KeyPressed { + key_code: KeyCode::Insert, + modifiers, + }) => { + if modifiers == Modifiers::SHIFT { + Some(Message::PastePrimary(None)) + } else { + None + } + } Event::Keyboard(KeyEvent::KeyPressed { key_code: KeyCode::Equals, modifiers, diff --git a/src/terminal_box.rs b/src/terminal_box.rs index 6d06515..af383af 100644 --- a/src/terminal_box.rs +++ b/src/terminal_box.rs @@ -575,7 +575,7 @@ where layout: Layout<'_>, cursor_position: mouse::Cursor, _renderer: &Renderer, - _clipboard: &mut dyn Clipboard, + clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, _viewport: &Rectangle, ) -> Status { @@ -977,6 +977,11 @@ where } } } + } else if let Button::Middle = button { + #[cfg(target_family = "unix")] + if let Some(value) = clipboard.read_primary() { + terminal.input_scroll(value.as_bytes().to_vec()); + } } // Update context menu state @@ -994,6 +999,13 @@ where } } Event::Mouse(MouseEvent::ButtonReleased(Button::Left)) => { + #[cfg(target_family = "unix")] + if let Some(Dragging::Buffer) = state.dragging { + let term = terminal.term.lock(); + if let Some(text) = term.selection_to_string() { + clipboard.write_primary(text); + } + } state.dragging = None; status = Status::Captured; } From e6fff76abd5c579ae4ed509ac0db063ee0ad240d Mon Sep 17 00:00:00 2001 From: Mattias Eriksson Date: Sat, 20 Jan 2024 14:27:16 +0100 Subject: [PATCH 2/6] Add missing target_family = "unix" gates --- src/key_bind.rs | 1 + src/main.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/key_bind.rs b/src/key_bind.rs index bf54cad..03b9b1f 100644 --- a/src/key_bind.rs +++ b/src/key_bind.rs @@ -61,6 +61,7 @@ pub fn key_binds() -> HashMap { bind!([Ctrl, Shift], Q, WindowClose); bind!([Ctrl, Shift], T, TabNew); bind!([Ctrl, Shift], V, Paste); + #[cfg(target_family = "unix")] bind!([Shift], Insert, PastePrimary); bind!([Ctrl, Shift], W, TabClose); diff --git a/src/main.rs b/src/main.rs index b1f6faa..55a1aa5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -174,6 +174,7 @@ pub enum Action { PaneSplitVertical, PaneToggleMaximized, Paste, + #[cfg(target_family = "unix")] PastePrimary, SelectAll, Settings, @@ -211,6 +212,7 @@ impl Action { Action::PaneSplitVertical => Message::PaneSplit(pane_grid::Axis::Vertical), Action::PaneToggleMaximized => Message::PaneToggleMaximized, Action::Paste => Message::Paste(entity_opt), + #[cfg(target_family = "unix")] Action::PastePrimary => Message::PastePrimary(entity_opt), Action::SelectAll => Message::SelectAll(entity_opt), Action::Settings => Message::ToggleContextPage(ContextPage::Settings), From 449803310ba565ada07a5f223e14d1ddd762293d Mon Sep 17 00:00:00 2001 From: Mattias Eriksson Date: Sun, 21 Jan 2024 16:56:23 +0100 Subject: [PATCH 3/6] Use terminal.paste() for middle click paste also --- src/terminal_box.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/terminal_box.rs b/src/terminal_box.rs index af383af..b1afe61 100644 --- a/src/terminal_box.rs +++ b/src/terminal_box.rs @@ -980,7 +980,7 @@ where } else if let Button::Middle = button { #[cfg(target_family = "unix")] if let Some(value) = clipboard.read_primary() { - terminal.input_scroll(value.as_bytes().to_vec()); + terminal.paste(value); } } From 45dd5aa46eac3dee6986c2226265ce33ca396ece Mon Sep 17 00:00:00 2001 From: Mattias Eriksson Date: Sun, 21 Jan 2024 21:13:13 +0100 Subject: [PATCH 4/6] Move most of the logic to main --- src/main.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++- src/terminal_box.rs | 23 +++++++++++------------ 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index 55a1aa5..43d1734 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use cosmic::{ clipboard, event, futures::SinkExt, keyboard::{Event as KeyEvent, KeyCode, Modifiers}, + mouse::{Button as MouseButton, Event as MouseEvent}, subscription::{self, Subscription}, window, Alignment, Event, Length, Padding, Point, }, @@ -165,6 +166,8 @@ pub struct Flags { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Action { Copy, + #[cfg(target_family = "unix")] + CopyPrimary, Find, PaneFocusDown, PaneFocusLeft, @@ -203,6 +206,8 @@ impl Action { pub fn message(self, entity_opt: Option) -> Message { match self { Action::Copy => Message::Copy(entity_opt), + #[cfg(target_family = "unix")] + Action::CopyPrimary => Message::CopyPrimary(entity_opt), Action::Find => Message::Find(true), Action::PaneFocusDown => Message::PaneFocusAdjacent(pane_grid::Direction::Down), Action::PaneFocusLeft => Message::PaneFocusAdjacent(pane_grid::Direction::Left), @@ -245,6 +250,7 @@ pub enum Message { AppTheme(AppTheme), Config(Config), Copy(Option), + CopyPrimary(Option), DefaultFont(usize), DefaultFontSize(usize), DefaultFontStretch(usize), @@ -257,6 +263,8 @@ pub enum Message { FindNext, FindPrevious, FindSearchValueChanged(String), + #[cfg(target_family = "unix")] + MiddleClick(pane_grid::Pane, Option), PaneClicked(pane_grid::Pane), PaneSplit(pane_grid::Axis), PaneToggleMaximized, @@ -916,6 +924,20 @@ impl Application for App { log::warn!("Failed to get focused pane"); } } + Message::CopyPrimary(entity_opt) => { + if let Some(tab_model) = self.pane_model.active() { + let entity = entity_opt.unwrap_or_else(|| tab_model.active()); + if let Some(terminal) = tab_model.data::>(entity) { + let terminal = terminal.lock().unwrap(); + let term = terminal.term.lock(); + if let Some(text) = term.selection_to_string() { + return clipboard::write_primary(text); + } + } + } else { + log::warn!("Failed to get focused pane"); + } + } Message::DefaultFont(index) => { match self.font_names.get(index) { Some(font_name) => { @@ -1050,6 +1072,17 @@ impl Application for App { Message::FindSearchValueChanged(value) => { self.find_search_value = value; } + #[cfg(target_family = "unix")] + Message::MiddleClick(pane, entity_opt) => { + self.pane_model.focus = pane; + return Command::batch([ + self.update_focus(), + clipboard::read_primary(move |value_opt| match value_opt { + Some(value) => message::app(Message::PasteValue(entity_opt, value)), + None => message::none(), + }), + ]); + } Message::Modifiers(modifiers) => { self.modifiers = modifiers; } @@ -1409,6 +1442,7 @@ impl Application for App { } let entity = tab_model.active(); + let entity_middle_click = tab_model.active(); let terminal_id = self .terminal_ids .get(&pane) @@ -1416,10 +1450,17 @@ impl Application for App { .unwrap_or_else(widget::Id::unique); match tab_model.data::>(entity) { Some(terminal) => { - let terminal_box = terminal_box(terminal).id(terminal_id).on_context_menu( + let mut terminal_box = terminal_box(terminal).id(terminal_id).on_context_menu( move |position_opt| Message::TabContextMenu(entity, position_opt), ); + #[cfg(target_family = "unix")] + { + terminal_box = terminal_box.on_middle_click(move || { + Message::MiddleClick(pane, Some(entity_middle_click)) + }); + } + let context_menu = { let terminal = terminal.lock().unwrap(); terminal.context_menu @@ -1529,6 +1570,9 @@ impl Application for App { Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => { Some(Message::Modifiers(modifiers)) } + Event::Mouse(MouseEvent::ButtonReleased(MouseButton::Left)) => { + Some(Message::CopyPrimary(None)) + } _ => None, }), subscription::channel( diff --git a/src/terminal_box.rs b/src/terminal_box.rs index b1afe61..b5ce7fb 100644 --- a/src/terminal_box.rs +++ b/src/terminal_box.rs @@ -47,6 +47,7 @@ pub struct TerminalBox<'a, Message> { click_timing: Duration, context_menu: Option, on_context_menu: Option) -> Message + 'a>>, + on_middle_click: Option Message + 'a>>, } impl<'a, Message> TerminalBox<'a, Message> @@ -61,6 +62,7 @@ where click_timing: Duration::from_millis(500), context_menu: None, on_context_menu: None, + on_middle_click: None, } } @@ -91,6 +93,11 @@ where self.on_context_menu = Some(Box::new(on_context_menu)); self } + + pub fn on_middle_click(mut self, on_middle_click: impl Fn() -> Message + 'a) -> Self { + self.on_middle_click = Some(Box::new(on_middle_click)); + self + } } pub fn terminal_box<'a, Message>(terminal: &'a Mutex) -> TerminalBox<'a, Message> @@ -575,7 +582,7 @@ where layout: Layout<'_>, cursor_position: mouse::Cursor, _renderer: &Renderer, - clipboard: &mut dyn Clipboard, + _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, _viewport: &Rectangle, ) -> Status { @@ -977,10 +984,9 @@ where } } } - } else if let Button::Middle = button { - #[cfg(target_family = "unix")] - if let Some(value) = clipboard.read_primary() { - terminal.paste(value); + } else if button == Button::Middle { + if let Some(on_middle_click) = &self.on_middle_click { + shell.publish(on_middle_click()); } } @@ -999,13 +1005,6 @@ where } } Event::Mouse(MouseEvent::ButtonReleased(Button::Left)) => { - #[cfg(target_family = "unix")] - if let Some(Dragging::Buffer) = state.dragging { - let term = terminal.term.lock(); - if let Some(text) = term.selection_to_string() { - clipboard.write_primary(text); - } - } state.dragging = None; status = Status::Captured; } From c90b5f67e5bb65afebae1c8e67cf6e284ca97254 Mon Sep 17 00:00:00 2001 From: Mattias Eriksson Date: Mon, 22 Jan 2024 08:10:57 +0100 Subject: [PATCH 5/6] Remove conditional compilation --- src/key_bind.rs | 1 - src/main.rs | 22 ++++++---------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/key_bind.rs b/src/key_bind.rs index 03b9b1f..bf54cad 100644 --- a/src/key_bind.rs +++ b/src/key_bind.rs @@ -61,7 +61,6 @@ pub fn key_binds() -> HashMap { bind!([Ctrl, Shift], Q, WindowClose); bind!([Ctrl, Shift], T, TabNew); bind!([Ctrl, Shift], V, Paste); - #[cfg(target_family = "unix")] bind!([Shift], Insert, PastePrimary); bind!([Ctrl, Shift], W, TabClose); diff --git a/src/main.rs b/src/main.rs index 43d1734..02edb54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -166,7 +166,6 @@ pub struct Flags { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Action { Copy, - #[cfg(target_family = "unix")] CopyPrimary, Find, PaneFocusDown, @@ -177,7 +176,6 @@ pub enum Action { PaneSplitVertical, PaneToggleMaximized, Paste, - #[cfg(target_family = "unix")] PastePrimary, SelectAll, Settings, @@ -206,7 +204,6 @@ impl Action { pub fn message(self, entity_opt: Option) -> Message { match self { Action::Copy => Message::Copy(entity_opt), - #[cfg(target_family = "unix")] Action::CopyPrimary => Message::CopyPrimary(entity_opt), Action::Find => Message::Find(true), Action::PaneFocusDown => Message::PaneFocusAdjacent(pane_grid::Direction::Down), @@ -217,7 +214,6 @@ impl Action { Action::PaneSplitVertical => Message::PaneSplit(pane_grid::Axis::Vertical), Action::PaneToggleMaximized => Message::PaneToggleMaximized, Action::Paste => Message::Paste(entity_opt), - #[cfg(target_family = "unix")] Action::PastePrimary => Message::PastePrimary(entity_opt), Action::SelectAll => Message::SelectAll(entity_opt), Action::Settings => Message::ToggleContextPage(ContextPage::Settings), @@ -263,7 +259,6 @@ pub enum Message { FindNext, FindPrevious, FindSearchValueChanged(String), - #[cfg(target_family = "unix")] MiddleClick(pane_grid::Pane, Option), PaneClicked(pane_grid::Pane), PaneSplit(pane_grid::Axis), @@ -273,7 +268,6 @@ pub enum Message { PaneResized(pane_grid::ResizeEvent), Modifiers(Modifiers), Paste(Option), - #[cfg(target_family = "unix")] PastePrimary(Option), PasteValue(Option, String), SelectAll(Option), @@ -1072,7 +1066,6 @@ impl Application for App { Message::FindSearchValueChanged(value) => { self.find_search_value = value; } - #[cfg(target_family = "unix")] Message::MiddleClick(pane, entity_opt) => { self.pane_model.focus = pane; return Command::batch([ @@ -1134,7 +1127,6 @@ impl Application for App { None => message::none(), }); } - #[cfg(target_family = "unix")] Message::PastePrimary(entity_opt) => { return clipboard::read_primary(move |value_opt| match value_opt { Some(value) => message::app(Message::PasteValue(entity_opt, value)), @@ -1450,16 +1442,14 @@ impl Application for App { .unwrap_or_else(widget::Id::unique); match tab_model.data::>(entity) { Some(terminal) => { - let mut terminal_box = terminal_box(terminal).id(terminal_id).on_context_menu( - move |position_opt| Message::TabContextMenu(entity, position_opt), - ); - - #[cfg(target_family = "unix")] - { - terminal_box = terminal_box.on_middle_click(move || { + let terminal_box = terminal_box(terminal) + .id(terminal_id) + .on_context_menu(move |position_opt| { + Message::TabContextMenu(entity, position_opt) + }) + .on_middle_click(move || { Message::MiddleClick(pane, Some(entity_middle_click)) }); - } let context_menu = { let terminal = terminal.lock().unwrap(); From 51eb4c5d0250ea1e0638d7813432900290ccc4d9 Mon Sep 17 00:00:00 2001 From: Mattias Eriksson Date: Wed, 10 Apr 2024 08:27:23 +0200 Subject: [PATCH 6/6] Adapt write_primary to libcosmic changes --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index e33e4f0..2569730 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1652,7 +1652,7 @@ impl Application for App { let terminal = terminal.lock().unwrap(); let term = terminal.term.lock(); if let Some(text) = term.selection_to_string() { - return clipboard::write_primary(text); + return Command::batch([clipboard::write_primary(text), self.update_focus()]); } } } else {